merges qt4 into trunk

git-svn-id: svn://svn.code.sf.net/p/qjoypad/code/trunk@94 c05e91a0-76c8-4ec0-b377-ef19ce7cc080
This commit is contained in:
John Toman
2009-08-03 00:46:33 +00:00
committed by virtuoussin13
parent 17ed926cdf
commit c1ef3fa0b7
12 changed files with 1596 additions and 1490 deletions

View File

@ -1,175 +1,286 @@
#include "unistd.h"
#include "joypad.h"
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <QApplication>
JoyPad::JoyPad( int i, int dev ) {
//remember the index,
index = i;
//load data from the joystick device, if available.
resetToDev(dev);
//there is no JoyPadWidget yet.
jpw = NULL;
//remember the index,
index = i;
//load data from the joystick device, if available.
joydevFileHandle = NULL;
if(dev > 0) {
resetToDev(dev);
joydevFileHandle = new QSocketNotifier(dev, QSocketNotifier::Read, this);
joydevFileException = new QSocketNotifier(dev, QSocketNotifier::Exception, this);
connect(joydevFileHandle, SIGNAL(activated(int)), this, SLOT(handleJoyEvents(int)));
connect(joydevFileException, SIGNAL(activated(int)), this, SLOT(errorRead(int)));
}
//there is no JoyPadWidget yet.
jpw = NULL;
}
void JoyPad::resetToDev(int dev ) {
//remember the device file descriptor
joydev = dev;
//remember the device file descriptor
joydev = dev;
//read in the number of axes / buttons
axes = 0;
ioctl (joydev, JSIOCGAXES, &axes);
buttons = 0;
ioctl (joydev, JSIOCGBUTTONS, &buttons);
//make sure that we have the axes we need.
//if one that we need doesn't yet exist, add it in.
//Note: if the current layout has a key assigned to an axis that did not
//have a real joystick axis mapped to it, and this function suddenly brings
//that axis into use, the key assignment will not be lost because the axis
//will already exist and no new axis will be created.
for (int i = 0; i < axes; i++) {
if (Axes[i] == 0) Axes.insert(i, new Axis( i ));
}
for (int i = 0; i < buttons; i++) {
if (Buttons[i] == 0) Buttons.insert(i, new Button( i ));
}
//read in the number of axes / buttons
axes = 0;
ioctl (joydev, JSIOCGAXES, &axes);
buttons = 0;
ioctl (joydev, JSIOCGBUTTONS, &buttons);
//make sure that we have the axes we need.
//if one that we need doesn't yet exist, add it in.
//Note: if the current layout has a key assigned to an axis that did not
//have a real joystick axis mapped to it, and this function suddenly brings
//that axis into use, the key assignment will not be lost because the axis
//will already exist and no new axis will be created.
for (int i = 0; i < axes; i++) {
if (Axes[i] == 0) Axes.insert(i, new Axis( i ));
}
for (int i = 0; i < buttons; i++) {
if (Buttons[i] == 0) Buttons.insert(i, new Button( i ));
}
struct pollfd read_struct;
read_struct.fd = joydev;
read_struct.events = POLLIN;
char buf[10];
while(poll(&read_struct, 1, 2)!=0) {
printf("reading junk data\n");
read(joydev, buf, 10);
}
setupJoyDeviceListener(dev);
}
void JoyPad::setupJoyDeviceListener(int dev) {
if(joydevFileHandle != NULL) {
delete joydevFileHandle;
}
joydevFileHandle = new QSocketNotifier(dev, QSocketNotifier::Read, this);
connect(joydevFileHandle, SIGNAL(activated(int)), this, SLOT(handleJoyEvents(int)));
}
void JoyPad::toDefault() {
//to reset the whole, reset all the parts.
for ( QIntDictIterator<Axis> it( Axes ); it.current(); ++it )
it.current()->toDefault();
for ( QIntDictIterator<Button> it( Buttons ); it.current(); ++it )
it.current()->toDefault();
//to reset the whole, reset all the parts.
do
{
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
} while (0);
do
{
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext())
{
it.next();
it.value()->toDefault();
}
} while (0);
}
bool JoyPad::isDefault() {
//if any of the parts are not at default, then the whole isn't either.
for ( QIntDictIterator<Axis> it( Axes ); it.current(); ++it )
if (!it.current()->isDefault()) return false;
for ( QIntDictIterator<Button> it( Buttons ); it.current(); ++it )
if (!it.current()->isDefault()) return false;
return true;
//if any of the parts are not at default, then the whole isn't either.
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext())
{
it.next();
if (!it.value()->isDefault()) return false;
}
} while (0);
do {
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext())
{
it.next();
if (!it.value()->isDefault()) return false;
}
} while (0);
return true;
}
bool JoyPad::read( QTextStream* stream ) {
toDefault();
bool JoyPad::readConfig( QTextStream* stream ) {
toDefault();
QString word;
QChar dump;
int num;
*stream >> word;
while (word != NULL && word != "}") {
word = word.lower();
if (word == "button") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Buttons[num-1] == 0) {
Buttons.insert(num-1,new Button(num-1));
}
if (!Buttons[num-1]->read( stream )) {
error("Layout file error", "Error reading Button " + QString::number(num));
return false;
}
}
else {
stream->readLine();
}
}
else if (word == "axis") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Axes[num-1] == 0) {
Axes.insert(num-1,new Axis(num-1));
}
if (!Axes[num-1]->read(stream)) {
error("Layout file error", "Error reading Axis " + QString::number(num));
return false;
}
}
}
else {
error( "Layout file error", "Error while reading layout. Unrecognized word: " + word );
return false;
}
*stream >> word;
}
return true;
QString word;
QChar dump;
int num;
*stream >> word;
while (word != NULL && word != "}") {
word = word.toLower();
if (word == "button") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Buttons[num-1] == 0) {
Buttons.insert(num-1,new Button(num-1));
}
if (!Buttons[num-1]->read( stream )) {
error("Layout file error", "Error reading Button " + QString::number(num));
return false;
}
}
else {
stream->readLine();
}
}
else if (word == "axis") {
*stream >> num;
if (num > 0) {
*stream >> dump;
if (dump != ':') {
error("Layout file error", "Expected ':', found '" + QString(dump) + "'.");
return false;
}
if (Axes[num-1] == 0) {
Axes.insert(num-1,new Axis(num-1));
}
if (!Axes[num-1]->read(stream)) {
error("Layout file error", "Error reading Axis " + QString::number(num));
return false;
}
}
}
else {
error( "Layout file error", "Error while reading layout. Unrecognized word: " + word );
return false;
}
*stream >> word;
}
return true;
}
//only actually writes something if this JoyPad is NON DEFAULT.
void JoyPad::write( QTextStream* stream ) {
int i = 0; //use to test if this is default or not.
QString result;
QTextStream* s = new QTextStream(&result, IO_WriteOnly);
*s << getName() << " {\n";
for ( QIntDictIterator<Axis> it( Axes ); it.current(); ++it ) {
//only write an axis if it is not at the default settings :)
if (!it.current()->isDefault()) {
it.current()->write( s );
++i;
}
}
for ( QIntDictIterator<Button> it( Buttons ); it.current(); ++it ) {
if (!it.current()->isDefault()) {
it.current()->write( s );
++i;
}
}
if (i > 0) {
*stream << result << "}\n\n";
}
int i = 0; //use to test if this is default or not.
QString result;
QTextStream* s = new QTextStream(&result, QIODevice::WriteOnly);
*s << getName() << " {\n";
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext()) {
it.next();
if (!it.value()->isDefault()) {
it.value()->write( s );
++i;
}
}
} while (0);
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext()) {
it.next();
if (!it.value()->isDefault()) {
it.value()->write( s );
++i;
}
}
if (i > 0) {
*stream << result << "}\n\n";
}
}
void JoyPad::release() {
for ( QIntDictIterator<Axis> it( Axes ); it.current(); ++it ) {
it.current()->release();
}
for ( QIntDictIterator<Button> it( Buttons ); it.current(); ++it ) {
it.current()->release();
}
do {
QHashIterator<int, Axis*> it( Axes );
while (it.hasNext()) {
it.next();
it.value()->release();
}
} while (0);
do {
QHashIterator<int, Button*> it( Buttons );
while (it.hasNext()) {
it.next();
it.value()->release();
}
} while (0);
}
void JoyPad::jsevent( js_event msg ) {
//if there is a JoyPadWidget around, ie, if the joypad is being edited
if (jpw != NULL) {
//tell the dialog there was an event. It will use this to flash
//the appropriate button, if necesary.
jpw->jsevent(msg);
}
//if the dialog is open, stop here. We don't want to signal ourselves with
//the input we generate.
if (qApp->activeWindow() != 0 && qApp->activeModalWidget() != 0) return;
//if there is a JoyPadWidget around, ie, if the joypad is being edited
if (jpw != NULL) {
//tell the dialog there was an event. It will use this to flash
//the appropriate button, if necesary.
jpw->jsevent(msg);
return;
}
//if the dialog is open, stop here. We don't want to signal ourselves with
//the input we generate.
if (qApp->activeWindow() != 0 && qApp->activeModalWidget() != 0) return;
//otherwise, lets create us a fake event! Pass on the event to whichever
//Button or Axis was pressed and let them decide what to do with it.
if (msg.type & JS_EVENT_AXIS) {
Axes[msg.number]->jsevent(msg.value);
}
else {
Buttons[msg.number]->jsevent(msg.value);
}
//otherwise, lets create us a fake event! Pass on the event to whichever
//Button or Axis was pressed and let them decide what to do with it.
if (msg.type & JS_EVENT_AXIS) {
printf("DEBUG: passing on an axis event\n");
printf("DEBUG: %d %d\n", msg.number, msg.value);
Axes[msg.number]->jsevent(msg.value);
}
else {
printf("DEBUG: passing on a button event\n");
printf("DEBUG: %d %d\n", msg.number, msg.value);
Buttons[msg.number]->jsevent(msg.value);
}
}
JoyPadWidget* JoyPad::widget( QWidget* parent, int i) {
//create the widget and remember it.
jpw = new JoyPadWidget(this, i, parent);
return jpw;
//create the widget and remember it.
jpw = new JoyPadWidget(this, i, parent);
return jpw;
}
void JoyPad::handleJoyEvents(int fd) {
js_event msg;
int len;
len = read( joydev, &msg, sizeof(js_event));
//if there was a real event waiting,
if (len == (int) sizeof(js_event)) {
//pass that event on to the joypad!
jsevent(msg);
}
//sleep for a moment. This is just to keep us from throwing all the
//available processer power into madly checking for new events.
//usleep(10000);
}
void JoyPad::releaseWidget() {
//this is how we know that there is no longer a JoyPadWidget around.
jpw = NULL;
//this is how we know that there is no longer a JoyPadWidget around.
jpw = NULL;
}
void JoyPad::unsetDev() {
close(joydev);
joydev = -1;
if(joydevFileHandle != NULL) {
delete joydevFileHandle;
}
}
void JoyPad::errorRead(int fd) {
joydevFileHandle->blockSignals(true);
joydevFileHandle->setEnabled(false);
close(joydev);
if(disconnect(joydevFileHandle , 0, 0, 0)) {
joydevFileHandle->deleteLater();
joydevFileHandle = NULL;
}
if(disconnect(joydevFileException, 0, 0, 0)) {
joydevFileException->setEnabled(false);
joydevFileException->deleteLater();
joydevFileException = NULL;
}
joydev = -1;
}