[ ] [] [ ]
Up: Libbraille documentation

Libbraille developer tutorial

Sébastien Sablé <sable@users.sourceforge.net>


Contents

This document explains how to develop using libbraille in the C/C++ languages. It is mostly intended for developers and not for simple users.

In this tutorial we will write a simple test program step by step that uses most functionalities of the Braille library. The complete test program is shown in annex and can be found in the test directory of the source distribution.

Generalities

Interaction with the Braille library is done through functions starting with the braille_ prefix. In order to use those functions, you need to include a braille.h header.

/* test.c - Test program and simple example */

#include <stdio.h>
#include <stdlib.h>
#include "braille.h" // the required header

Most libbraille functions can return an error, usually by returning 0. In this case, it is possible to get a string describing precisely the problem by calling the braille_geterror() function.

if(!braille_init())
  {
    fprintf(stderr, "Error initialising libbraille: %s\n", braille_geterror());
    return 1;
  }

Configuration

In order to run, libbraille must use a driver specific to the connected Braille display; it also needs to know what Braille table should be used to convert ASCII characters to Braille, as well as the port to which the display is connected.

Parameters like the Braille display or port can usally be autodetected so that it is not necessary to specify them. All parameters can also be configured through a configuration file [TODO: or through the windows registry on windows platforms].

However, an application may want to provide its own configuration system to configure libbraille parameters. In order to permit that, libbraille provides some functions to configure and request the current configuration.

Driver configuration

The list of available drivers can be obtained with the following functions:

braille_drivernum()
returns the number of available drivers
braille_drivername(i)
returns the name of driver number i
braille_drivermodels(i)
returns a string describing the models supported by driver number i

The following example shows how those functions can be used:

for(i = 0; i < braille_drivernum(); i++)
  {
    printf("driver [%d]: %s, supporting models: %s", i, braille_drivername(i),
	     braille_drivermodels(i));
    printf("\n");
  }

Once the name of the driver to use has been selected, it can be configured in libbraille by using the braille_config like in this example where ``once'' is the name of a driver:

braille_config(BRL_DRIVER, "once");

Note that there is a special driver named ``auto''. This driver can be used when the Braille display should be autodetected.

Braille table configuration

The list of available Braille tables can be obtained with the following functions:

braille_tablenum()
returns the number of available tables
braille_tablename(i)
returns the name of table number i
braille_tabledesc(i)
returns a string describing the Braille table number i

The following example shows how those functions can be used:

for(i = 0; i < braille_tablenum(); i++)
  {
    printf("table [%d]: %s, corresponding to: %s", i, braille_tablename(i),
	     braille_tabledesc(i));
    printf("\n");
  }

Once the name of the table to use has been selected, it can be configured in libbraille by using the braille_config like in this example where ``french.tbl'' is the name of a table:

braille_config(BRL_TABLE, "french.tbl");

Misc configuration

The braille_config function can be used to configure other parameters by changing the first argument:

BRL_DEVICE
to configure the port where the display is connected
BRL_PATH
(in windows) to configure the path where libbraille have been installed
BRL_PATHCONF
(unix only) to configure the path where the configuration file can be found
BRL_PATHDRV
to configure the path where additionnal drivers can be found
BRL_PATHTBL
to configure the path where additionnal tables can be found

A complete example:

braille_config(BRL_DEVICE, "COM1");
braille_config(BRL_DRIVER, "auto");
braille_config(BRL_TABLE, "foo.tbl");
braille_config(BRL_PATH, "/foo/bar/");

Initialisation

The braille_init function should be called right after configuration, before any other function of the library. It will parse the configuration file, autodetect the Braille display if necessary, load the correct driver and Braille table then initialise and configure the Braille display.

if(!braille_init())
  {
    fprintf(stderr, "Error initialising libbraille: %s\n", braille_geterror());
    return 1;
  }

Query configuration

Once the library has been initialised, it is possible to query the configuration that is used by using the braille_config function with a specific parameter:

BRL_DEVICE
to query the port where the display is connected
BRL_DRIVER
to query the name of the Braille display driver
BRL_TERMINAL
to query for the model of Braille display which is connected
BRL_TABLE
to query the name of the Braille table
BRL_PATH
to query the path where libbraille data files have been found
BRL_PATHCONF
(unix only) to query the path where the configuration file can be found
BRL_PATHDRV
to query the path where additionnal drivers can be found
BRL_PATHTBL
to query the path where additionnal tables can be found
BRL_VERSION
to query the version of libbraille

The braille_size() function returns the number of cells of Braille display. The braille_statussize() function returns the number of additionnal cells for the status area.

printf("Libbraille version %s initialised correctly "
       "with driver %s using terminal %s with %d cells on device %s\n",
       braille_info(BRL_VERSION), braille_info(BRL_DRIVER),
       braille_info(BRL_TERMINAL), braille_size(),
       braille_info(BRL_DEVICE));

Displaying a Simple String

The easiest way to write something on the Braille display is to use the braille_display function. It must be called with a string terminated by NULL and will display that string on the display.

braille_display("test_libbraille started");

Advanced dots displaying

There is a more complex function to display something, when a better control of what is displayed is necessary, for example when displaying something other than text. What will be displayed is a combination of text and a filter that directly manipulates dots.

First you set the text with braille_write. Contrarly to braille_display, this function does not take a NULL terminated string as parameter, but a pointer to some chars and a number indicating the number of chars to read.

Then you use braille_filter to raise some dots. The first argument of braille_filter is an unsigned char corresponding to which dots have to be activated. The second argument is the number of the cell which has to be modified, starting at 0.

The dots 1, 2, 3, 4, 5, 6 and 7 correspond respectively to bits 0, 1, 2, 3, 4, 5, 6 and 7 of the unsigned char. For example, a cursor made of dots 7 and 8 corresponds to the binary number 00000011. There is a BRAILLE macro that makes it simple to get the correct value. It just takes as parameters the state of each dot.

Finally, braille_render is called. This function filters the text given by braille_write with the filter defined through braille_filter and send the data to the Braille display.

The following example display some text with a cursor under the first character:

{  
  char *hello_msg = "more complex test";

  braille_write(hello_msg, strlen(hello_msg)); 
  braille_filter(BRAILLE(0, 0, 0, 0, 0, 0, 1, 1), 0);
  braille_render();
}

Typing with the Braille Keyboard

Most Braille displays have some keys like cursors or function keys to interact with the computer. Some even feature a Braille keyboard to input text. Libbraille makes it possible to get an event when some of those keys are pressed by using the braille_read function.

Setting the timeout

Depending on the application, it is sometime necessary to control how much time a function can take before returning. There is a function called braille_timeout to configure how the braille_read function should behave:

blocking
in this mode, braille_read will wait forever that a key is pressed on the display. This mode is set by passing -1 to braille_timeout.
immediat return
in this mode, braille_read will test if a key has been pressed and return immediately after. This mode is set by passing 0 to braille_timeout.
time limited
in this mode, braille_read will wait at most during a given time that a key is pressed on the display. This mode is set by passing a time expressed in milliseconds to braille_timeout.

Reading data

When a key is pressed or at the time limit, the braille _read function returns a structure of type brl_key describing the event that happened.

The structure has an attribute named type describing the type of key pressed. It can have a few values:

BRL_NONE
in this case, no key has been pressed. The function returned because of a timeout
BRL_CURSOR
a ``cursor routing'' key has been pressed. Those are the keys which are just above the Braille cells. In this case, the code attribute contains the number starting at 0 of the cell for which the cursor routing key has been pressed.
BRL_CMD
a ``function'' key has been pressed. Those are keys with a special function like validate, read further on the right or move at the top of the page. The code attribute contains a code depending on the function key. There are many codes which can be found in the braille.h header file.
BRL_KEY
the user has typed some ASCII characters on the display. The code attribute gives the ASCII value [TODO: and unicode provides the unicode value] of the character.

/* we want the braille_read function to wait forever while no key
   has been pressed */
braille_timeout(-1);

/* get the keys pressed on the display */
while(1)
  {
    signed char status;
    brl_key key;
    
    status = braille_read(&key);
    if(status == -1)
      {
        printf("error in braille_read: %s",
	       braille_geterror());
      }
    else if(status)
      {
     printf("Read key with type %d and code %d\n",
            key.type, key.code);
     switch(key.type)
       {
        case BRL_NONE:
          break;
        case BRL_CURSOR:
          printf("cursor: %d\n", key.code);
          break;
        case BRL_CMD:
          printf("command: ");
          switch(key.code)
    	{
    	case BRLK_HOME:
    	  printf("home\n");
    	  break;
    	case BRLK_BACKWARD:
    	  braille_display("backward");
    	  printf("reading further left on the display\n");
    	  break;
    	case BRLK_FORWARD:
    	  braille_display("forward");
    	  printf("reading further right on the display\n");
    	  break;
    	default:
    	  printf("unknown cmd\n");
    	  break;
    	}
          break;
        case BRL_KEY:
          printf("braille: 0x%x\n", key.braille);
          printf("code: %d ou 0x%x\n", key.code, key.code);
          printf("char: %c\n", key.code);
          break;
        default:
          printf("unknown type %d\n", key.type);
        }
    }
  }

Stopping the Library

Finally, the braille_close function must always be called when closing the Braille library. It will unload the driver, free resources and close the library.

braille_close();
printf("Leaving test_libbraille\n");

Compiling

Libbraille is made of a shared library. In order to use it you need to link the library to your program.

For Visual C++ developpers, you need to add the libbraille-1.lib file to your project. An example Visual C++ project and the .lib file is available on the download page of the web site as libbraille-dev-x.x.x-VC6.zip

For unix developpers, linking the library is just a matter of adding the -lbraille option at compile time. For example, compiling the previous test code would be :

    cc test.c -o test -lbraille

Annex

/*
 * test_libbraille.c - Test program and simple example
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "braille.h"

int 
main(int argc, char *argv[])
{
  int i;

  printf("Starting test_libbraille\n");

  for(i = 0; i < braille_drivernum(); i++)
    {
      printf("driver [%d]: %s, supporting models: %s", i, braille_drivername(i),
	     braille_drivermodels(i));
      printf("\n");
    }

  for(i = 0; i < braille_tablenum(); i++)
    {
      printf("table [%d]: %s, corresponding to: %s", i, braille_tablename(i),
	     braille_tabledesc(i));
      printf("\n");
    }

  /* uncomment to config some values without using the configuration
     file */
  /* braille_config(BRL_DEVICE, "COM1"); */
  /* braille_config(BRL_DRIVER, "eco"); */
  /* or braille_config(BRL_DRIVER, "auto"); */
  /* braille_config(BRL_TABLE, "foo.tbl"); */
  /* braille_config(BRL_PATH, "/foo/bar/"); */
  /* ... */

  if(!braille_init())
    {
      fprintf(stderr, "Error initialising libbraille: %s\n",
                      braille_geterror());
      
      fprintf(stderr, "Testing fake driver\n");
      braille_config(BRL_DRIVER, "none");
      if(!braille_init())
	{
	  fprintf(stderr, "Error initialising libbraille: %s\n",
                          braille_geterror());
	  return 1;
	}
    }

  printf("Libbraille version %s initialised correctly " \
	 "with driver %s using terminal %s with %d cells on device %s\n",
	 braille_info(BRL_VERSION), braille_info(BRL_DRIVER),
	 braille_info(BRL_TERMINAL), braille_size(),
	 braille_info(BRL_DEVICE));

  /* we want the braille_read function to wait forever while no key
     has been pressed */
  // braille_timeout(-1);

  /* we want the braille_read function to wait at most 1s while no key
     has been pressed */
  braille_timeout(1000);

  printf("displaying string\n");
  /* simple way to display something */
  braille_display("test_libbraille started");

  /* complex and powerful way to display something */
  {
    char *hello_msg = "test_libbraille started";

    braille_write(hello_msg, strlen(hello_msg)); 
    braille_filter(BRAILLE(0, 0, 0, 0, 0, 0, 1, 1), 0);
    braille_filter(BRAILLE(0, 0, 0, 0, 0, 0, 1, 1), 23);
    braille_render();
  }

  /* Displaying a few things on the status cells */
  if(braille_statussize() > 0)
    braille_statusdisplay("abc");

  /* get the keys pressed on the display */
  while(1)
    {
      signed char status;
      brl_key key;
      
      status = braille_read(&key);
      if(status == -1)
	{
	  printf("error in braille_read: %s", braille_geterror());
	}
      else if(status)
	{
	  printf("Read key with type %d and code %d\n", key.type, key.code);
	  switch(key.type)
	    {
	    case BRL_NONE:
	      break;
	    case BRL_CURSOR:
	      printf("cursor: %d\n", key.code);
	      break;
	    case BRL_CMD:
	      printf("command: ");
	      switch(key.code)
		{
		case BRLK_HOME:
		  printf("home\n");
		  break;
		case BRLK_BACKWARD:
		  braille_display("backward");
		  printf("reading further left on the display\n");
		  break;
		case BRLK_FORWARD:
		  braille_display("forward");
		  printf("reading further right on the display\n");
		  break;
		default:
		  printf("unknown cmd\n");
		  break;
		}
	      break;
	    case BRL_KEY:
	      printf("braille: 0x%x\n", key.braille);
	      printf("code: %d ou 0x%x\n", key.code, key.code);
	      printf("char: %c\n", key.code);
	      break;
	    default:
	      printf("unknown type %d\n", key.type);
	    }
	}
    }

  /* now we stop everything */
  braille_close();

  printf("Leaving test_libbraille\n");
  return 0;
}

[ ] [] [ ]
Up: Libbraille documentation
Copyright 2004 Sébastien Sablé - 2004-11-21
SourceForge Logo