Thursday, October 25, 2012

How to disable/change/load dirvers without restarting?

How to disable/unload some driver for your current session without restarting ?

If the driver is a Loadable Kernel Module (LKM) then you are in luck, (Drivers are LKMs most of the times, don't worry :) )

all you have to do is

                           $modprobe -r <module name>

What if you want to disable module across reboots without re-running above command ?

In this case you can blacklist the module. To do it, add following line

                           blacklist <module name>

to

                           /etc/modprobe.d/blacklist.conf

file.
Be sure to use sudo or root privilege for modifying the file, else you will not be allowed to modify it.

Blacklisting modules can be very useful, sometimes for disabling misbehaving modules or sometimes for disabling unnecessary modules, like floppy drivers (I don't see a computer that still has floppy drive!).

Lets assume that you removed/unloaded a module in current session, what if you want to load it back for what-so-ever reason. I have one reason, one of my driver misbehaves sometimes, unloading and loading it back helps fixing it rather than restarting my machine, though this may not be the best solution, this is the easiest one that I have found so far!

run following command to re-load module. (This command inserts the module).

                           $modprobe <module name>

for more info on modprobe, use man pages, they are always very good source of information.

You can also replace your old drivers with new ones without restarting your computer

                           $modprobe -r <old module>
                           $modprobe <newmodule>

Sunday, October 21, 2012

A simple OCR (Optical Character Recognition)

Couple of weeks back, I decided to work on OCR tool. Some years back I had tried my hands on OpenCV, and I knew that it would be a good place to start, since this library comes with lot of algorithms for real-time image processing.

When searched on google for basic OCR to start with I found http://blog.damiles.com/2008/11/basic-ocr-in-opencv/. The same link also has very nice explanation of how it works. This basic OCR was written to recognize hand written numbers. This program was also written with assumption that each image to be recognized will have only one character.

I took a fork out of this project and modified it. I added samples for upper case character(Update: and for lower case characters) and did necessary changes so that the program would identify the upper-case characters(Update: and lower case letters), with same assumption that image to be recognized will have only one character.

 Then I wrote a simple algorithm to recognize multiple characters in an image containing paragraph of text. There are some assumptions built into this algorithm, but not very big ones if considered for recognition of regular text on documents.

Assumptions(or limitations) built into the algorithm are
  1. Between each row of text there would be gap of at-least one row which would be at-least one pixel thick. Shown as red(well almost :) ) line in the image below.
  2. Between each character on same row there would be gap of at-least one column which would be at-least one pixel thick as well. Shown as green line in the image.
  3. For any given character there wouldn't be gap between different parts of the character, although this limitation can be overcome by small change in algorithm, since only uppercase letters are used in current example, this assumption will hold good and speeds up both learning and recognition phases, this also means that if same algorithm is used for recognizing lower case characters then it will fail for i and j. since both have gap between different parts of the character. Update: This limitation has been removed by improving the algorithm.

I will not explain everything in detail, since it can be found at damile's blog, I have explained below the algorithm I have used to find characters in an image of paragraph of characters. Other changes that I have made to actual source should be fairly simple to understand.

The algorithm I have used is very simple,

Algorithm

for each row in the image from row 0 to height of image
        if sum of current row > sum of(width of image*255)
             save current row number as maxY 
             if minY has not been found already then
                 save current row number as minY
        else if minY has been found then /*some data has been found along row already, after finding some data as soon as some blank row is reached, it is considered as end of end of character */
             for each column from column 0 to width of image
                 if sum of current column from minY to max Y > sum of((maxY-minY)*255)
                      save current column number as maxX
                      if minX has not been found already then
                           save current column number as minX
                 else if minX has been found then
                        resize minY and maxY if necessary /*necessary if one of the characters in current row is bigger in-terms of height than others like A vs Q */
                        match image from (minX, minY) to (maxX,maxY) to a character.

Code

The algorithm may look very big, but its very simple. :) Here is the code for this algorithm

/// <summary>
///     Given image with paragraph of characters,
///     finds bounding box, resizes it to new_width and new_height, and if printResult is 1, prints result for each character.
/// </summary>
/// <params name="imsSrc">
///     Source image which has to be processed.
/// </params>
/// <params name="new_width">
///     Width of the image to be used for processing.
/// </params>
/// <params name="new_height">
///     Height of the image to be used for processing.
/// </params>
/// <params name="printResult">
///     Indicates whether result has be printed, if its 1, result are printed after running k-neares algorithm.
/// </params>
/// <params name="resultSize">
///     Number of resulting characters identified, size of the array to which result will be pointing to.
/// </params>
/// <returns> Pointer to array of result. </returns>
float* OCR::preprocessPara(IplImage* imgSrc, int new_width, int new_height, int printResult, int* resultSize)
{
    int minY, maxY;
    int i;
    int minYFound=0;
    float result;
    vector<float> resultVector;
    float* resultPointer;
    CvMat data;
    CvScalar maxVal=cvRealScalar(imgSrc->width * 255);
    CvScalar val=cvRealScalar(0);
    //For each column sum, if sum < width*255 then we find the min
    //then continue till end to search the max, if sum< width*255 then is new max.
        for (i=0; i< imgSrc->height; i++)
        {
            cvGetRow(imgSrc, &data, i);
            val= cvSum(&data);
            if(val.val[0] < maxVal.val[0])
            { // some data is found!
                maxY = i;
                if(!minYFound)
                {
                    minY = i;
                    minYFound = 1;
                }
            }
            else if(minYFound == 1)
            {
                //some data was found previously, but current row 'i' doesn't have any data.
                //So process from row 'minY' till row maxY
                int j;
                int minX, maxX;
                int minXFound=0;
                //CvMat data;
                CvScalar maxValx=cvRealScalar((maxY - minY) * 255);
                CvScalar valx=cvRealScalar(0);
                //For each col sum, if sum < width*255 then we find the min
                //then continue to end to search the max, if sum< width*255 then is new max
                for (j=0; j< imgSrc->width - 1; j++)
                {
                    valx=cvRealScalar(0);
                    //instead of taking sum of entire column get sum of sub part of it.
                    cvGetSubRect(imgSrc,&data, cvRect(j,minY,1,maxY-minY));
                    //cvGetCol(imgSrc, &data, i);
                    valx= cvSum(&data);
                    if(valx.val[0] < maxValx.val[0])
                    { //Some data found
                        maxX= j;
                        if(!minXFound){
                            minX= j;
                            minXFound= 1;
                        }
                    }
                    else if(minXFound == 1)
                    {
                        int maxYp;

                        CvScalar maxValyS = cvRealScalar((maxX-minX)*255);
                        CvScalar valyS = cvRealScalar(0);
                        // from minx to maxx and miny to maxy
                        for(int k=maxY-1; k >= minY; k--)
                        {
                            cvGetSubRect(imgSrc, &data, cvRect(minX, k, maxX-minX,1));
                            valyS = cvSum(&data);
                            if(valyS.val[0] < maxValyS.val[0])
                            {
                                maxYp = k+1;
                                break;
                            }
                        }
                        //Some data was found previosly but current column 'j' doesn't have any data.
                        // so from minY to maxY and minX to maxX is the bounding box of character!
                        result = process(imgSrc, new_width, new_height, printResult, cvRect(minX, minY, maxX-minX, maxYp-minY));
                        resultVector.push_back(result); // after finding each result push the result to the vector.
                        minXFound = 0;
                    }
                }

                minYFound = 0;
            }
        }
    //If exit from loop was because max height was reached, but minFound has been set, then process from minFound till height.
    //This will not happen in the ideal examples I take :)
    *resultSize = resultVector.size();
    resultPointer = new float[*resultSize];
    int k;
    for(k = 0; k < *resultSize; k++)
    {
        *(resultPointer+k) = resultVector[k];
    }

    return resultPointer;
}

k-nearest neighbors algorithm has been used to match test image vs training images. Its simple and fast.

Source code can be found at https://github.com/vikram-ma/OCR.
Github is really nice, If you have not tried it already you should!, so is git

Sample of images for each character for training has been put inside separate directory and has a data.txt file having corresponding character which image represent.

Build and run

Instructions for build, go inside source-code directory, type-in following commands on console,

                                $mkdir build
                                $cd build
                                $cmake ../OCR
                                $make

running

./OCR <path to directory containing sample images> <path to sample test image>

specifically,

                               $./OCR ../OCR ../sampleUppercase.pbm

Feel free to leave your feedback and questions, I will try to answer them as quickly as possible.

Tuesday, August 28, 2012

Web caching! how relevant is it?

Why is caching done ?

It is done as an optimization step. Motive behind it, is to
  1. Reduce lag at the client side.
  2. Reduce load on the servers.
  3. Reduce the required bandwidth network infrastructure has to support.

Mostly web caching refers to caching of content by some intermediate machines or servers that are heavily accessed through it.

Caching can be done at different levels,

Following excerpt is from Wikipedia article Web_cache which explains some of the places content is cached.

Web caches can be used in various systems.
  1. A search engine may cache a website.
  2. A forward cache is a cache outside the web-server's network, e.g. on the client software's ISP or company network.
  3. A network-aware forward cache is just like a forward cache but only caches heavily accessed items.
  4. A reverse cache sits in front of one or more Web servers and web applications, accelerating requests from the Internet.
  5. A client, such as a web browser, can store web content for reuse. For example, if the back button is pressed, the local cached version of a page may be displayed instead of a new request being sent to the web server.
  6. A web proxy sitting between the client and the server can evaluate HTTP headers and choose to store web content.
  7. A content delivery network can retain copies of web content at various points throughout a network.

Now, does web caching still has some relevance left?

So let us consider this,

             How much time do you spend on the web browsing through general web pages, i.e. pages that are as seen by you can be seen AS IS by someone else sitting somewhere else?
           Mostly answer is not much, its because most of the pages that you use are personalized.

Read newspaper ? Probably you have personalized your news to suit your taste.
Read feeds? You have again personalized the contents that you want to read from.

          These two places you personalized the look & feel, presentation. But the content inside will be the ones which others can see.

But consider this,

Your mail,
Your social networking account
And many other kinds of accounts,

           All these are strictly personal,they are meant for you only. Going by the rules of caching heavily accessed content these data will be cached rarely. You are not the only one out there who are trying to access personal content.

           Forward cache, reverse cache, network aware cache and web proxy don't considers factors of personalization. Unless some of these servers are meant just for you!(in that case your are rich), or a group of small people

That leaves us with three more,

Web browser - this is the best place to cache content from personalization point of view, but what about data that is constantly changing, your social network feeds, your news, you mails.

Search engine - this place can be used to cache trending articles and results for most queried search terms. (How long can  same article be trending upwards?)

Content delivery - how many of you have not heard of content on demand? This serves the purpose of delivering what content you want and when you want. If some new movie is released (or any other content), it will have high demand on initial days, gradually demand for it also reduces.

           Since the content you browse are personalized, simply caching heavily accessed content doesn't work! Its relevance has reduced. Caching can be done to only certain extent. Replicating the servers to multiple places is the way forward.

           So my opinion here is that, "relevance of web caching going by the rules of caching heavily accessed content has reduced in the era of personalization if not completely eliminated"

Do leave your comments and opinions! Lets have an open discussion.

Thursday, August 23, 2012

Sniffer for Linux

 Introduction 

          To completely understand the article I expect the reader to know basic concept of network, different terms used in it and some C programming.

          This article explains how a small program can be used to sniff packets from the network. I worked on this about 21/2  years back. I didn't get a chance to share this back then. Content of this article is for Ubuntu and its derivatives. (It can be achieved on Microsoft Windows as well with some modifications to the code presented in this article and related changes to commands )

Content

           Before I start keep in mind that whenever I say network its LAN unless specified to be something else.

           The idea presented here is simple, with just few lines of code and some very good libraries(thanks to open source community), you can write a very strong tool which can be used to sniff packets out of the network, not just the packets that are meant for your machine, but the ones that are addressed to any machine on same network.

This is how packets reach the destination computer on LAN

           Whenever a packet reaches gateway, it verifies that if the destination is one of the computers in the LAN for which it is gateway. If yes then IP addresses are converted to corresponding MAC addresses using ARP protocol and then frames are forwarded to LAN, then the repeaters(if any) flood the LAN with these frames.

            So all the computers in LAN read these frames to match the destination MAC address against theirs. If it doesn't match then the frames are discarded else it is passed along the network stack.

This is what makes it possible to sniff frames

              It is possible to tell the computer to pass each frame up the network stack for any MAC address i.e its own MAC address and others'.  If you are able to achieve this, then you are sniffing! This is also called as Promiscuous mode.

So how do we achieve this?

Here is the code to do it. 

#include <pcap.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/time.h>
#define SIZE_ETHERNET 14
#define SNAP_LEN 1518

/* IP header */
struct sniff_ip {
  u_char  ip_vhl;                 /* version << 4 | header length >> 4 */
  u_char  ip_tos;                 /* type of service */
  u_short ip_len;                 /* total length */
  u_short ip_id;                  /* identification */
  u_short ip_off;                 /* fragment offset field */
  #define IP_RF 0x8000            /* reserved fragment flag */
  #define IP_DF 0x4000            /* don't fragment flag */
  #define IP_MF 0x2000            /* more fragments flag */
  #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
  u_char  ip_ttl;                 /* time to live */
  u_char  ip_p;                   /* protocol */
  u_short ip_sum;                 /* checksum */
  struct  in_addr ip_src,ip_dst;  /* source and destination address */
};

#define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip)                (((ip)->ip_vhl) >> 4)

/* TCP header */
typedef u_int tcp_seq;

struct sniff_tcp {
  u_short th_sport;               /* source port */
  u_short th_dport;               /* destination port */
  tcp_seq th_seq;                 /* sequence number */
  tcp_seq th_ack;                 /* acknowledgement number */
  u_char  th_offx2;               /* data offset, rsvd */
#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
  u_char  th_flags;
  #define TH_FIN  0x01
  #define TH_SYN  0x02
  #define TH_RST  0x04
  #define TH_PUSH 0x08
  #define TH_ACK  0x10
  #define TH_URG  0x20
  #define TH_ECE  0x40
  #define TH_CWR  0x80
  #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
  u_short th_win;                 /* window */
  u_short th_sum;                 /* checksum */
  u_short th_urp;                 /* urgent pointer */
};

//
//Prints the payload to stdout or to fd 1. 
//
void print_hex_ascii_line(const u_char *payload, int len, int offset)
{
 const u_char *ch;

 ch = payload;
 int i;
 int gap;
 
 for(i=0; i<len; i++)
 {
  printf("%02x ",*ch);
  ch++;
  if(i==7)
   printf(" ");
 }
 if(len < 8)
  printf(" ");
 
 if (len < 16) 
 {
  gap = 16 - len;
  for (i = 0; i < gap; i++) 
  {
   printf("   ");
  }
 }

 printf("   ");

 ch = payload;
 for(i=0; i<len; i++)
 {
  if(isprint(*ch))
   printf("%c",*ch);
  else
   printf(".");
 
  ch++;
 }
 
 printf("\n");

 return;
}
 
//
//Does book-keeping work required to print the payload. 
//
void print_payload(const u_char *payload, int len)
{ 
 int len_rem = len;
 int line_width = 16;                    
 int line_len;
 int offset = 0;                          
 const u_char *ch = payload;
 
 if (len <= 0)
  returnif (len <= line_width) 
 {
  print_hex_ascii_line(ch, len, offset);
  return;
 }

 for ( ;; ) 
 {
  line_len = line_width % len_rem;
  print_hex_ascii_line(ch, line_len, offset);
  len_rem = len_rem - line_len;
  ch = ch + line_len;
  if (len_rem <= line_width) 
  {
   print_hex_ascii_line(ch, len_rem, offset);
   break;
  }
 }
 
 return;
}

int cnt=1;

//
// Prints the details of the packet captured
// Packet number.
// Protocol, Of course this program will always print tcp packets because of the filter used. :)
// Source IP address. 
// Destination IP address. 
//
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
 
 const struct sniff_ip *ip;  /* IP header */
 const struct sniff_tcp *tcp;            /* The TCP header */
 char *payload;

 int size_ip;
  int size_tcp;
  int size_payload;
 
 ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
 size_ip = IP_HL(ip)*4;

 printf("packet number %d\n",cnt);   // Prints the packet number. 
 cnt++;
 switch(ip->ip_p) {                  // Prints the protocol. 
  case IPPROTO_TCP:
   printf("   Protocol: TCP\n");
   break;
  case IPPROTO_UDP:
   printf("   Protocol: UDP\n");
   return;
  case IPPROTO_ICMP:
   printf("   Protocol: ICMP\n");
   return;
  case IPPROTO_IP:
   printf("   Protocol: IP\n");
   return;
  default:
   printf("   Protocol: unknown\n");
   return;
 }
 printf("       From: %s\n", inet_ntoa(ip->ip_src)); //Prints source IP address. 
 printf("         To: %s\n", inet_ntoa(ip->ip_dst)); //Prints destination IP address. 
 
 tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
 size_tcp = TH_OFF(tcp)*4;
 
 payload = (u_char*)(packet + SIZE_ETHERNET + size_ip + size_tcp);
 size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
 
 if (size_payload > 0) {
    printf("   Payload (%d bytes):\n", size_payload);
    print_payload(payload, size_payload);
 }
}

int main(int c,char *v[])
{
 char *dev;
 char errbuf[PCAP_ERRBUF_SIZE];
 char filter_exp[]="tcp"// Filter expression is set to tcp, so it captures only TCP packets. 
 pcap_t *handle;
 struct bpf_program fp;
 bpf_u_int32 net;
 bpf_u_int32 mask;
 if(c==2)
 {
  dev=v[1];
 }
 else if(c>2)
 {
  printf("unidentified  options\n");
  return 1;
 }
 else
 {
  dev=pcap_lookupdev(errbuf); // Checks for the default device. 
  if(dev==NULL)
  {
   fprintf(stderr,"couldn't find the default device %s\n",errbuf);
   return 1;
  }
 }
 printf("Probing device %s\n",v[1]);
 pcap_lookupnet(dev,&mask,&net,errbuf); // Gets the details of the device. 
 handle=pcap_open_live(dev,SNAP_LEN,1,1000,errbuf); // Opens the device for capturing the packets. 
 if(pcap_compile(handle,&fp,filter_exp,0,net) == -1) // Compilation with filter_exp. 
 {
  fprintf(stderr,"no valid filter expression");
  return 1;
 }
 pcap_setfilter(handle,&fp); // Sets the filter as tcp. 
 pcap_loop(handle,200,got_packet,NULL); // Sets the call-back method which would be called every time a packet is captured. 
 
 return 0; // Returns 0 if everything goes well. 
}
 

How to compile the code?

            First you have install the libraries that I was talking about, use the following command on Ubuntu or any other derivatives (for fedora use yum).

                 $ sudo apt-get install libpcap-dev

Us the following command to compile using gcc. 

                 $ gcc -o sniffer sniffer.c -lpcap

You can always crate makefile and make to build to save you from trouble of compiling every time.

How to run it?

If you are connected to network via wifi then,

                 $ sudo ./sniffer wlan0

(Here wlan0 identifies your device to be used to sniff packets)

If you are using wired connection then following command should suffice.

                 $ sudo ./sniffer

Its because eth0 is usually the default device for wired connections, which libraries will pick up directly, you don't have to explicitly set the device. But you can always explicitly specify the device. 

You can find out which device to use by running

                 $ ifconfig

it will list all the network interfaces, choose active one, usually its the one for which inet address, broadcast, mask and other details are assigned to, unless you are connected via two network interfaces simultaneously.

Here is the sample output

packet number 21
   Protocol: TCP
       From: 74.125.135.84
         To: 192.168.1.2
   Payload (133 bytes):
16 03 01 00 51 02 00 00  4d 03 01 50 36 37  97 dd    ....Q...M..P67..
2e 7c 49 6c 4d 7e a8  f c  e5 2f  c3 5c 2c  a0 12 32    .|IlM~.../.\,..2
e2 b2 43 9c 56 77 57 6f   2f a6 57 20 8b  0e 89 44    ..C.VwWo/.W ...D
ef  9a 31 b2 01 8a cc f3   ea 02 cd 59 01  e8  78 39    ..1........Y..x9
81 07 e0 9c 90 7b 2c f8   f9 40 6b 94 c0  11 00 00    .....{,..@k.....
05 ff  01 00 01 00 14 03   01 00 01 01 16  03 01 00    ................
24 9b c8 38 11 cb ea 21   1c 3a c3 8d 12  aa 4a 3d    $..8...!.:....J=
9e a1 03 14 57 9e 9b dd   ba 46 dc ba 18  ee f7  f8    ....W....F......
95 fd 84  6e 71                                                           ...nq

Do leave your feedback!

Q&A

1. The packet number in the above output is 21. What does it mean?

 First let me explain why multiple packets are used for communication
           For every communication that happens between computers via network (LAN, WLAN or any type of network), information is interchanged between them through series of packets that are sent and received by both computers. If information to be sent is too big to be sent in single packet, its divided into smaller chunks and sent as series of packets.

From the perspective of above program what number 21 mean?
         Packet number 21 means that from the time that this Sniffer has started executing, it has caught 20 packets already, and the above one is 21st.

Every time Sniffer is started,
Count is set to 1,
/*The below section is looped every time a packet is captured by sniffer */
For every packet captured,
                     it prints the Count as number of packet captured.
                     then Count is incremented by one and
                     prints all other details.
/*Looped till here */

This includes all the packets, including the ones that are sent and received by the machine that is running this Sniffer.

Saturday, August 11, 2012

Installing Linux Mint Maya on USB for a computer with Nviida GPU

          I have been a long term user of Linux. I had never tried installing persistent Linux on pen drive before, so gave it a try.

         I have listed below how I achieved this to help others who may want to try it. Before we start its essential to know your hardware,

My Hardware:

Core i7, NVIDIA GF108 [Quadro 1000M], 4 GB DDR3 RAM.

These are the things that matter  most.
Currently I am using Windows 7 OS.

Before we start, note that

Contents of this tutorial is valid only for Ubuntu ands its variants. (With little variations this can be applied for other flavors as well, googling will help you )

Things we need for this tutorial are

  1. Pen drive(at-least 2 GB). 
  2. Computer running Windows or Linux. Capable of booting from USB drive(thats basically anything thats manufactured in last 4 or 5 years). 
  3. Ubuntu or one of its variants.
  4.  UNetbootin software.

Steps!

         1. Download your favorite OS. I prefer Linux Mint. (Yes, Mint is based on Ubuntu)
You can find Mint here. I tried hands on KDE 64 bit version, but you can take your pick.There is one particular reason why prefer mint, it comes preloaded with many softwares, video and audio CODECS, which means you can play any music and movie out of the box and you don't miss out on the support of strong Ubuntu community.

        2.  Download UNetbootin. You can find it here.
Run it, you should be seeing window like this. 



           3.  Navigate to the downloaded OS, by choosing Diskimage and browse button,
           4.  Choose the amount of persistent storage you want in the space used to preserve files across reboots section.( I used 4096 MB, I am using 16 GB pen drive :) ).
         5.  Choose your USB Drive.

Hit OK,

It may look like UNetbootin has hung when it has finished about 80 to 90%, but don't worry its common, it takes about 10 min to finish. 
Once your done, reboot.

           6.  While rebooting(Before Windows logo appears!) hit Esc and choose boot from USB Drive,(this may be different for you, depending on your hardware, go through manual for you hardware to find ways to chose USB Drive as boot medium).

          7.  Navigate to "Try Linux Mint without installing" option and press TAB, add

              nouveau.modeset=0

after quiet splash. This is essential if you are using Nvidia GPU like me, otherwise Linux will not boot!. This step is to disable use of GPU. (Don't worry next step explains how to enable GPU).
              If you are not using nvidia GPU then you don't need this step and next step.

         8.  After booting has finished, open terminal( press Alt-F2 and choose Konsole) run following commands.

This adds repository for installing driver

               sudo add-apt-repository ppa:ubuntu-x-swat/x-updates

This will update the repository information

                sudo apt-get update 

 This installs nvidia dirvers.

               sudo apt-get install nvidia-current

This configures the drivers. 
 
               sudo nvidia-xconfig

Following command is for restarting X-server on KDE,

               sudo restart kdm

If you are using Gnome then

               sudo restart gdm

for information on how to restart other x-servers google it, you will find answers, or let me know I will help you out.


And you are done! These settings will be preserved across reboots.

If everything goes well you should be seeing something like this.


If you run into any trouble, feel free to contact me, do leave your feedback!



Thursday, May 10, 2012

WPF Slider with annotations.

 Some days back I was looking for a way to annotate the tick-mars on the slider.

Again I will show what was the problem I was trying to solve.


Below Slider there are ticks, I wanted to annotate them with some meaningful labels. Unfortunately Slider doesn't have any APIs that would help me achieve this.

One of the obvious solutions that comes to mind is strategically placing the WPF Label control below the tick marks, but this will make this feature non-extensible. Each time you change the number of tick marks, you will have to update the label positions so that they come exactly below the tick marks. Something like this,


As you can see, I have failed at placing the labels correctly below the ticks, that is because I was limited by Visual Studio at choosing the nearest position, but not the exact location.

I did Google to search for the answers and found relevant information here and here.

The above post told everything except, tick marks were being replaced by string, but I wanted both tick marks and text!.

I started modifying the Slider control to include API that will accept comma(,) separated string to display below the ticks. Something like "1,,3,,5". I have placed two commas to let know the API that I don't want anything to displayed below the second or fourth tick marks. And I modified the algorithm a little so that I will not require Margin as mentioned in above post to correct the position of text below text. If I had used Margin it would have affected the placement of ticks along with that text, as a result the tick marks would have been misplaced.

Here is the algorithm that I used.

 public class CustomTickBar : TickBar
    {
        protected override void OnRender(DrawingContext dc)
        {
            string[] textArray = TickBarText.Split(',');
            FormattedText formattedText;
            Size size = new Size(base.ActualWidth, base.ActualHeight);
            double num = this.Maximum - this.Minimum;
            double num5 = this.ReservedSpace * 0.5;
            size.Width -= this.ReservedSpace;
            double tickFrequencySize = (size.Width * this.TickFrequency / (this.Maximum - this.Minimum));
            int j = 0;
            for (double i = 0; i <= num; i += this.TickFrequency)
            {
                string annotation;
                try
                {
                    annotation = textArray[j];
                }
                catch (System.IndexOutOfRangeException)
                {
                    annotation = "";
                }
                formattedText = new FormattedText(annotation, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), 8, Brushes.Black);
                dc.DrawText(formattedText, new Point((tickFrequencySize * i) + num5-(formattedText.Width/2), 10));
                j++;
            }
            
            base.OnRender(dc); //This is essential so that tick marks are displayed. 
         } 
     }

Here is the sample output.
 

Whats more, since the tick bar is now part of slider itself, it can respond to property changes
Slider, like when the control is disabled the annotated text can gray out!


Tuesday, May 1, 2012

Inline ScrollViewer

Before I start explaining, let me show you the problem I was trying to solve,

As it can be seen from the image above, to scroll a single line of statement, real-estate required is twice that of actual data itself. 50% of the space has gone waste!

 So came up with this,

It did save space, though not 50%!. Some amount of space has been lost to the scroll button themselves.

Then I was inspired by scroll bar provided VS for browsing options on right click of project file, where the scroll buttons are removed/collapsed if  it can't be scrolled any further. Specifically in the image above the left scroll button doesn't make sense, since we are already at leftmost position, same applies to right scroll button when we have reached end.

 This is what I achieved at the end.




I have written below the style I used for scrollviewer. (In case if you need further clarifications feel free to contact me.)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomScroller.Controls">
    <Style TargetType="{x:Type local:CustomScrollViewer}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomScrollViewer}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition />
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition />
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <RepeatButton x:Name="PART_LeftRepeatButton" Grid.Row="1" Grid.Column="0" Command="ScrollBar.LineLeftCommand">
                            <Path Fill="#FF444444" Stroke="#FF444444" Data="M 0,5 L 5,0 L 5,10 Z"/>
                        </RepeatButton>
                        <RepeatButton x:Name="PART_UpRepeatButton" Grid.Row="0" Grid.Column="1" Command="ScrollBar.LineUpCommand">
                            <Path Fill="#FF444444" Stroke="#FF444444" Data="M 0,5 L 5,0 L 10,5 Z"/>
                        </RepeatButton>
                        <ScrollContentPresenter Grid.Row="1" Grid.Column="1" />
                        <RepeatButton x:Name="PART_RightRepeatButton" Grid.Row="1" Grid.Column="2" Command="ScrollBar.LineRightCommand">
                            <Path Fill="#FF444444" Stroke="#FF444444" Data="M 0,0 L 5,5 L 0,10 Z"/>
                        </RepeatButton>
                        <RepeatButton x:Name="PART_DownRepeatButton" Grid.Row="2" Grid.Column="1" Command="ScrollBar.LineDownCommand">
                            <Path Fill="#FF444444" Stroke="#FF444444" Data="M 0,0 L 10,0 L 5,5 Z"/>
                        </RepeatButton>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
 

Here is the part of the code that decides when to show which repeat buttons.

 
//Updates the visiblity of Left and Right Repeat buttons. 
    leftRepeatButton.Visibility = ComputedHorizontalScrollBarVisibility;
    rightRepeatButton.Visibility = ComputedHorizontalScrollBarVisibility;
         
      if (ContentHorizontalOffset == 0)
      {
         leftRepeatButton.Visibility = Visibility.Collapsed;
      }
 
      if (ContentHorizontalOffset == ExtentWidth - ViewportWidth)
      {
        rightRepeatButton.Visibility = Visibility.Collapsed;
      }
    
 
//Updates the visiblity of Up and Down Repeat buttons. 
    upRepeatButton.Visibility = ComputedVerticalScrollBarVisibility;
    downRepeatButton.Visibility = ComputedVerticalScrollBarVisibility;

      if (ContentVerticalOffset == 0)
      {
        upRepeatButton.Visibility = Visibility.Collapsed;
      }
      if (ContentVerticalOffset == ExtentHeight - ViewportHeight)
      {
        downRepeatButton.Visibility = Visibility.Collapsed;
      }