Let's now see how one can write dedicated applications. Basic notions will be seen, along with a very simple client. Greater details are given as online manual pages.
The historical test program for BrlAPI was something like:
It is here rewritten, its working briefly explained.
Connection to BrlAPI is needed first, thanks to the
brlapi_openConnection
call. For this, a
brlapi_connectionSettings_t
variable must be filled which will hold the
settings the library needs to connect to the server. Just giving NULL
will work for local use. The other parameter lets you get back the parameters
which were actually used to initialize connection. NULL
will also be nice
for now.
if (brlapi_openConnection(NULL, NULL)<0) {
brlapi_perror("brlapi_openConnection");
exit(1);
}
The connection might fail, so testing is needed.
Knowing the type of the braille device might be useful:
char name[BRLAPI_MAXNAMELENGTH+1];
if (brlapi_getDriverName(name, sizeof(name)) < 0)
brlapi_perror("brlapi_getDriverName");
else
fprintf(stderr, "Driver name: %s\n", name);
This is particularly useful before entering raw mode to achieve file transfers for instance, just to check that the device is really the one expected.
Before writing on the braille display, the size should be always first checked to be sure everything will hold on it:
if (brlapi_getDisplaySize(&x, &y) < 0)
brlapi_perror("brlapi_getDisplaySize");
else
fprintf(stderr, "Braille display has %d line%s of %d column%s\n",
y, y>1?"s":"", x, x>1?"s":"");
Entering raw mode is very simple:
fprintf(stderr, "Trying to enter in raw mode... ");
if (brlapi_enterRawMode(name) < 0)
brlapi_perror("brlapi_enterRawMode");
else {
fprintf(stderr, "Ok, leaving raw mode immediately\n");
brlapi_leaveRawMode();
}
Not every driver supports raw mode, so testing is needed.
While in raw mode, brlapi_sendRaw
and brlapi_recvRaw
can be used to send and get data directly to and from the device.
It should be used with care, improper use might completely thrash the device!
Let's now display something on the device. control of the tty must be get first:
fprintf(stderr, "Taking control of the tty... ");
if (brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT, NULL) >= 0)
{
fprintf(stderr, "Ok\n");
The first parameter tells the server the number of the tty to take control of. Setting BRLAPI_TTY_DEFAULT lets the library determine it for us.
The server is asked to send brltty commands, which are device-independent.
Getting control might fail if, for instance, another application already took control of this tty, so testing is needed.
From now on, the braille display is detached from the screen.
The application can now write things on the braille display without altering the screen display:
fprintf(stderr, "Writing to braille display... ");
if (brlapi_writeText(0, "Press a braille key to continue...") >= 0)
{
fprintf(stderr, "Ok\n");
The cursor is also asked not to be shown: its position is set to 0.
"Writing to braille display... Ok" is now displayed on the screen, and "Press a braille key to continue..." on the braille display.
To have a break for the user to be able to read these messages, a key press (a command here, which is driver-independent) may be waited for:
fprintf(stderr, "Waiting until a braille key is pressed to continue... ");
if (brlapi_readKey(1, &key) > 0)
fprintf(stderr, "got it! (code=%"BRLAPI_PRIxKEYCODE")\n", key);
The command is returned, as described in <brlapi_constants.h>
and <brlapi_keycodes.h>
.
It is not transmitted to brltty: it is up to the application to define
the behavior, here cleanly exitting, as described below.
The first parameter tells the lib to block until a key press is indeed read.
There are two kinds of commands: braille commands (line up/down, top/bottom, etc.) and X Keysyms (i.e. regular keyboard keys). One way to discover which key was pressed is to just use a switch statement:
switch(key) {
case BRLAPI_KEY_TYPE_CMD|BRLAPI_KEY_CMD_LNUP:
fprintf(stderr, "line up\n");
break;
case BRLAPI_KEY_TYPE_CMD|BRLAPI_KEY_CMD_LNDN:
fprintf(stderr, "line down\n");
break;
case BRLAPI_KEY_TYPE_SYM|XK_Tab:
fprintf(stderr, "tab\n");
break;
default:
fprintf(stderr, "unknown key\n");
break;
}
Another way is to ask BrlAPI to expand the keycode into separate information parts:
brlapi_expandedKeyCode_t ekey;
brlapi_expandKeyCode(key, &ekey);
fprintf(stderr, "type %u, command %u, argument %u, flags %u\n",
ekey.type, ekey.command, ekey.argument, ekey.flags);
Eventually, named equivalents are provided:
brlapi_describedKeyCode_t dkey;
int i;
brlapi_describeKeyCode(key, &dkey);
fprintf(stderr, "type %s, command %s, argument %u, flags",
dkey.type, dkey.command, dkey.argument);
for (i = 0; i < dkey.flags; i++)
fprintf(stderr, " %s", dkey.flag[i]);
fprintf(stderr, "\n");
Let's now leave the tty:
fprintf(stderr, "Leaving tty... ");
if (brlapi_leaveTtyMode() >= 0)
fprintf(stderr, "Ok\n");
But control of another tty can still be get for instance, by calling
brlapi_enterTtyMode()
again...
Let's disconnect from BrlAPI:
brlapi_closeConnection();
The application can as well still need to connect to another server on another
computer for instance, by calling brlapi_openConnection()
again...
#include <stdio.h>
#include <stdlib.h>
#include <brlapi.h>
int main()
{
brlapi_keyCode_t key;
char name[BRLAPI_MAXNAMELENGTH+1];
unsigned int x, y;
/* Connect to BrlAPI */
if (brlapi_openConnection(NULL, NULL)<0)
{
brlapi_perror("brlapi_openConnection");
exit(1);
}
/* Get driver name */
if (brlapi_getDriverName(name, sizeof(name)) < 0)
brlapi_perror("brlapi_getDriverName");
else
fprintf(stderr, "Driver name: %s\n", name);
/* Get display size */
if (brlapi_getDisplaySize(&x, &y) < 0)
brlapi_perror("brlapi_getDisplaySize");
else
fprintf(stderr, "Braille display has %d line%s of %d column%s\n",
y, y>1?"s":"", x, x>1?"s":"");
/* Try entering raw mode, immediately go out from raw mode */
fprintf(stderr, "Trying to enter in raw mode... ");
if (brlapi_enterRawMode(name) < 0)
brlapi_perror("brlapi_enterRawMode");
else {
fprintf(stderr, "Ok, leaving raw mode immediately\n");
brlapi_leaveRawMode();
}
/* Get tty control */
fprintf(stderr, "Taking control of the tty... ");
if (brlapi_enterTtyMode(BRLAPI_TTY_DEFAULT, NULL) >= 0)
{
fprintf(stderr, "Ok\n");
/* Write something on the display */
fprintf(stderr, "Writing to braille display... ");
if (brlapi_writeText(0, "Press a braille key to continue...") >= 0)
{
fprintf(stderr, "Ok\n");
/* Wait for a key press */
fprintf(stderr, "Waiting until a braille key is pressed to continue... ");
if (brlapi_readKey(1, &key) > 0) {
brlapi_expandedKeyCode_t ekey;
brlapi_describedKeyCode_t dkey;
int i;
fprintf(stderr, "got it! (code=%"BRLAPI_PRIxKEYCODE")\n", key);
brlapi_expandKeyCode(key, &ekey);
fprintf(stderr, "type %u, command %u, argument %u, flags %u\n",
ekey.type, ekey.command, ekey.argument, ekey.flags);
brlapi_describeKeyCode(key, &dkey);
fprintf(stderr, "type %s, command %s, argument %u, flags",
dkey.type, dkey.command, dkey.argument);
for (i = 0; i < dkey.flags; i++)
fprintf(stderr, " %s", dkey.flag[i]);
fprintf(stderr, "\n");
} else brlapi_perror("brlapi_readKey");
} else brlapi_perror("brlapi_writeText");
/* Leave tty control */
fprintf(stderr, "Leaving tty... ");
if (brlapi_leaveTtyMode() >= 0)
fprintf(stderr, "Ok\n");
else brlapi_perror("brlapi_leaveTtyMode");
} else brlapi_perror("brlapi_enterTtyMode");
/* Disconnect from BrlAPI */
brlapi_closeConnection();
return 0;
}
This should compile well thanks to
gcc apiclient.c -o apiclient -lbrlapi