Linux-Joystick

 view release on metacpan or  search on metacpan

Joystick.pm  view on Meta::CPAN


	# assume that $input represents some stream such as a keyboard
	# or network socket, and $js is our Linux::Joystick device. Further
	# assume that $input is opened in non-blocking mode (it shouldn't
	# matter for $js, since the kernel *always* returns 8 bytes per event).

	# adapted from `perldoc -f select', which see for details.

	while(1) {
		my $buf; # $input buffer
		my $BUFLEN = 1024; # size of $input buffer

		my $rin = '';
		for($js->fileHandle, $input) {
			vec($rin, fileno($_), 1) = 1;
		}

		# 4th parameter is timeout. 0 means return immediately,
		# undef means block forever, anything else is number of
		# seconds to wait. $nfound will tell how many fd's had
		# input pending, which really isn't too useful...

		my $nfound = select($rin, undef, undef, undef);

		if( vec($rin, fileno($js->fileHandle), 1) == 1 ) {
			my $event = $js->nextEvent();
			process_event($event); # or whatever
		}

		if( vec($rin, fileno($input), 1) == 1 ) {
			# GOTCHA: do NOT use <$input> here! (see select() perldoc)
			while( ($bytes = sysread($input, $buf, $BUFLEN) > 0) ) {
				# process $input data one buffer at a time
				process_input($buf);
			}
		}
	}

Notice that the above routine doesn't read from the filehandle returned
by $js->fileHandle. Instead it's just used in the select() call.

You can make that a lot more readable by using the IO::Select module
instead of all that mess with vec() and select().

Of course, variations on this theme are possible. You could use the
Curses or IO::Stty modules to read one character at a time from STDIN,
in which case you'd just process one keystroke per loop iteration...

=head2 $js->setNonblocking


Sets or clears non-blocking mode. Takes one scalar parameter, which
is treated as a boolean: a true value turns on non-blocking I/O, and
a false value turns it off. It doesn't hurt anything to attempt to set
the same mode that's already in use, and you can switch between the I/O
modes as many times as you want.

setNonblocking uses an fcntl() call to change the file descriptor's mode,
so it doesn't close and reopen the device. Remember that when you're in
non-blocking mode, all calls to nextEvent immediately return. When there's
no input, the event returned will be undef. Also remember not to busy-wait
on events! If you find yourself using 99% of the CPU according to `top',
you need to restructure your code so that it works in blocking mode. If
you can't do this (e.g. because you're reading from a network socket as
well as a joystick), at least use a call like select(undef, undef, undef,
0.01) to yield the CPU so that other processes can run.  An even better
idea would be to stay in blocking mode, but use the fileHandle method
to get the joystick's file handle, then select() on both the joystick
and network filehandles. This way, the kernel will put your process to
sleep until there's some input available on one stream or the other.

Since setNonblocking uses fcntl(), it may behave strangely on really old
(2.2 or earlier) kernels. I have only tested this module on Linux 2.4
and 2.6 kernels.

=head1 Events


	$ev->isButton
	$ev->button
	$ev->buttonDown
	$ev->buttonUp
	$ev->isAxis
	$ev->axis
	$ev->axisValue
	$ev->stickLeft
	$ev->stickRight
	$ev->stickUp
	$ev->stickDown
	$ev->type
	$ev->hexDump
	$ev->timeStamp

=head2 $ev->isButton


Returns true if this event was caused by a button press, or false if not.

The next 3 method calls are only valid for button events (e.g. when
isButton returns true). If called on a non-button event, they will
return undef.

=head2 $ev->button


Returns the number of the button that caused this event, if it was
a button event, or undef it it wasn't a button event. Keep in mind that
0 is a valid button (it's the first button), so you don't want to
treat this as a boolean (use isButton instead).

NOTE: In the Linux joystick API, each button is reported separately,
even if more than one button was pressed or released simultaneously. For
example, pressing 2 buttons at once on a gamepad results in 2 events:
one for each button. This may sound like a problem, but in practice it
works out just fine if you process each event as soon as it comes in.

=head2 $ev->buttonDown

=head2 $ev->buttonDown($b);




( run in 1.009 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )