VRPN main page

Obtaining VRPN

VRPN Support

Installing and Testing

Compiling and Modifying

Client code

Server code

Troubleshooting

Connections

Logging and Playback

Shared Objects

Clock Synchronization

Coming attractions & suggestions

UNC-specific information

Table of Contents

Selections from the #include file

// User routine to handle a change in button state.  This is called when
// the button callback is called (when a message from its counterpart
// across the connetion arrives).

typedef	struct {
	struct timeval	msg_time;	// Time of button press/release
	int		button;		// Which button (numbered from zero)
	int		state;		// New state (0 = off, 1 = on)
} vrpn_BUTTONCB;
typedef void (*vrpn_BUTTONCHANGEHANDLER)(void *userdata,
					 const vrpn_BUTTONCB info);

// Open a button that is on the other end of a connection
// and handle updates from it.  This is the type of button that user code will
// deal with.

#define BUTTON_MOMENTARY 10
#define BUTTON_TOGGLE_OFF    20
#define BUTTON_TOGGLE_ON    21
#define ALL_ID		-99

class vrpn_Button_Remote: public vrpn_Button {
  public:
	// The name of the button device to connect to
	vrpn_Button_Remote(char *name);

	// This routine calls the mainloop of the connection it's on
	virtual void mainloop(void);

	// (un)Register a callback handler to handle a button state change
	virtual int register_change_handler(void *userdata,
		vrpn_BUTTONCHANGEHANDLER handler);
	virtual int unregister_change_handler(void *userdata,
		vrpn_BUTTONCHANGEHANDLER handler);
        //call in the remote device to set the
        //buttons to be momentary or toggle.
        //A momentery button comes on only as long as it is held down.
        //A toggle button comes on when it is pressed and then goes off when
        //it is pressed again. Use ALL_ID to set the mode for all buttons.
        int set_button_mode(int mode, int button_id);
};

Using a vrpn_Button_Remote

A vrpn_Button_Remote object is used by passing the name of the button device you want to connect to as a parameter to the constructor, defining a callback handler that with respond to the button state update messages, and then calling its mainloop() message each time through the program's main loop. The callback handler takes care of updated implementing what should happen on a button press or release. Here is a simple example program that just prints the new state of each button as the reports arrive:

#include <stdlib.h>
#include <stdio.h>
#include <vrpn_Button.h>


/*****************************************************************************
 *
   Callback handler
 *
 *****************************************************************************/

void	handle_button(void *userdata, vrpn_BUTTONCB b)
{
	printf("B%ld is %ld\n", b.button, b.state);
}

int main(int argc, char *argv[])
{	int	done = 0;
	vrpn_Button_Remote *btn;

	/* initialize the button */
	btn = new vrpn_Button_Remote("Button0@ioglab");

	// Set up the button callback handler
	btn->register_change_handler(NULL, handle_button);

/* 
 * main interactive loop
 */
while ( ! done )
    {
	// Let the  button do its thing
	btn->mainloop();
    }

}   /* main */

Callback function

The vrpn_Button_Remote class provides information on changes in the button states by calling a user callback function. The application gives the function that should handle the data, and also a pointer to a block of user data that the callback routine needs in order to handle the data. For example, if the callback function was supposed to adjust a certain color field based on button presses then a pointer to the color field might be passed as user data. If the callback handler was going to affect some object, a pointer to the object would be passed. In this case, the handler function would typecast the 'void *userdata' pointer to the correct type for the user data. If more than one data item is to be passed, they should be placed into a structure and a pointer to the structure passed as user data.