static void testCallbacks() { EventDispatcher * dispatcher; char * sender1 = "1", * sender2 = "2"; int callback1Context = 0, callback2Context = 0; int incrementation = 2; bool handled; Atom event1Atom, event2Atom; dispatcher = EventDispatcher_create(sender1); event1Atom = Atom_fromString("event1"); event2Atom = Atom_fromString("event2"); handled = dispatcher->dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(!handled, "Event handled when no callbacks are registered"); dispatcher->registerForEvent(dispatcher, event1Atom, callback1, &callback1Context); handled = dispatcher->dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(handled, "Event not handled when appropriate callback was registered"); TestCase_assert(callback1Context == 2, "Expected 2 but got %d", callback1Context); TestCase_assert(lastSender == sender1, "Expected %p but got %p", sender1, lastSender); incrementation = 3; dispatcher->dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback1Context == 2, "Callback called for wrong type of event"); dispatcher->registerForEvent(dispatcher, event2Atom, callback2, &callback2Context); handled = dispatcher->dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback2Context == 3, "Expected 3 but got %d", callback2Context); TestCase_assert(!handled, "Expected false but got true"); dispatcher->unregisterForEvent(dispatcher, event1Atom, callback1, NULL); handled = dispatcher->dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(handled, "Event not still handled after unregistering callbacks with the wrong context"); dispatcher->unregisterForEvent(dispatcher, event1Atom, callback1, &callback1Context); handled = dispatcher->dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(!handled, "Event still handled after unregistering callbacks"); incrementation = 1; handled = dispatcher->dispatchEvent(dispatcher, event2Atom, &incrementation); TestCase_assert(callback2Context == 4, "Expected 4 but got %d", callback2Context); TestCase_assert(!handled, "Expected false but got true"); dispatcher->dispose(dispatcher); dispatcher = EventDispatcher_create(sender2); dispatcher->registerForEvent(dispatcher, event1Atom, callback1, &callback1Context); dispatcher->dispatchEvent(dispatcher, event1Atom, &incrementation); TestCase_assert(lastSender == sender2, "Expected %p but got %p", sender2, lastSender); dispatcher->dispose(dispatcher); }
bool Preferences_init(Preferences * self) { call_super(init, self); self->private_ivar(hashTable) = hashCreate(); self->eventDispatcher = EventDispatcher_create(); self->dispose = Preferences_dispose; return true; }
void StateController_init(StateController * self) { call_super(init, self); self->dispose = StateController_dispose; self->addState = StateController_addState; self->setState = StateController_setState; self->addTransition = StateController_addTransition; self->transition = StateController_transition; self->eventDispatcher = EventDispatcher_create(self); self->currentState = NULL; self->validStateCount = 0; self->validStates = NULL; self->transitionCount = 0; self->transitions = NULL; }
bool InputPlayback_init(InputPlayback * self, InputController * inputController, InputSession * inputSession) { call_super(init, self); self->dispose = InputPlayback_dispose; self->step = InputPlayback_step; self->rewind = InputPlayback_rewind; self->inputController = inputController; self->inputSession = inputSession; self->eventDispatcher = EventDispatcher_create(self); self->frameIndex = 0; self->lastFrameIndex = 0; if (inputSession == NULL || inputSession->actionCount == 0) { self->actionsTriggered = NULL; } else { self->actionsTriggered = calloc(sizeof(bool), inputSession->actionCount); } self->eventIndex = 0; return true; }
bool InputController_vinit(InputController * self, InputMap * inputMap, va_list args) { va_list argsCopy; call_super(init, self); self->dispose = InputController_dispose; self->keyDown = InputController_keyDown; self->keyUp = InputController_keyUp; self->keyModifiersChanged = InputController_keyModifiersChanged; self->gamepadButtonDown = InputController_gamepadButtonDown; self->gamepadButtonUp = InputController_gamepadButtonUp; self->gamepadAxisMoved = InputController_gamepadAxisMoved; self->triggerAction = InputController_triggerAction; self->releaseAction = InputController_releaseAction; self->reset = InputController_reset; self->eventDispatcher = EventDispatcher_create(self); self->inputMap = inputMap; self->lastModifiers = 0x0; self->actionCount = 0; self->actions = NULL; va_copy(argsCopy, args); while (va_arg(argsCopy, const char *) != NULL) { self->actionCount++; } va_end(argsCopy); if (self->actionCount > 0) { unsigned int actionIndex; self->actions = malloc(sizeof(struct InputController_action) * self->actionCount); for (actionIndex = 0; actionIndex < self->actionCount; actionIndex++) { self->actions[actionIndex].actionID = Atom_fromString(va_arg(args, const char *)); self->actions[actionIndex].triggered = false; } }
void Gamepad_detectDevices() { unsigned int numPaths; char ** gamepadPaths; bool duplicate; unsigned int pathIndex, gamepadIndex; struct stat statBuf; struct Gamepad_device * deviceRecord; struct Gamepad_devicePrivate * deviceRecordPrivate; int fd; char name[128]; char * description; int evKeyBits[(KEY_CNT - 1) / sizeof(int) * 8 + 1]; int evAbsBits[(ABS_CNT - 1) / sizeof(int) * 8 + 1]; int bit; struct input_id id; if (!inited) { return; } gamepadPaths = findGamepadPaths(&numPaths); pthread_mutex_lock(&devicesMutex); for (pathIndex = 0; pathIndex < numPaths; pathIndex++) { duplicate = false; for (gamepadIndex = 0; gamepadIndex < numDevices; gamepadIndex++) { if (!strcmp(((struct Gamepad_devicePrivate *) devices[gamepadIndex]->privateData)->path, gamepadPaths[pathIndex])) { duplicate = true; break; } } if (duplicate) { free(gamepadPaths[pathIndex]); continue; } if (!stat(gamepadPaths[pathIndex], &statBuf)) { deviceRecord = (Gamepad_device*)malloc(sizeof(struct Gamepad_device)); deviceRecord->deviceID = nextDeviceID++; deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord); devices = (Gamepad_device**)realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1)); devices[numDevices++] = deviceRecord; fd = open(gamepadPaths[pathIndex], O_RDONLY, 0); deviceRecordPrivate = (Gamepad_devicePrivate*)malloc(sizeof(struct Gamepad_devicePrivate)); deviceRecordPrivate->fd = fd; deviceRecordPrivate->path = gamepadPaths[pathIndex]; memset(deviceRecordPrivate->buttonMap, 0xFF, sizeof(deviceRecordPrivate->buttonMap)); memset(deviceRecordPrivate->axisMap, 0xFF, sizeof(deviceRecordPrivate->axisMap)); deviceRecord->privateData = deviceRecordPrivate; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) { description = (char*)malloc(strlen(name + 1)); strcpy(description, name); } else { description = (char*)malloc(strlen(gamepadPaths[pathIndex] + 1)); strcpy(description, gamepadPaths[pathIndex]); } deviceRecord->description = description; if (!ioctl(fd, EVIOCGID, &id)) { deviceRecord->vendorID = id.vendor; deviceRecord->productID = id.product; } else { deviceRecord->vendorID = deviceRecord->productID = 0; } memset(evKeyBits, 0, sizeof(evKeyBits)); memset(evAbsBits, 0, sizeof(evAbsBits)); ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits); ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits); deviceRecord->numAxes = 0; for (bit = 0; bit < ABS_CNT; bit++) { if (test_bit(bit, evAbsBits)) { if (ioctl(fd, EVIOCGABS(bit), &deviceRecordPrivate->axisInfo[bit]) < 0 || deviceRecordPrivate->axisInfo[bit].minimum == deviceRecordPrivate->axisInfo[bit].maximum) { continue; } deviceRecordPrivate->axisMap[bit] = deviceRecord->numAxes; deviceRecord->numAxes++; } } deviceRecord->numButtons = 0; for (bit = BTN_MISC; bit < KEY_CNT; bit++) { if (test_bit(bit, evKeyBits)) { deviceRecordPrivate->buttonMap[bit - BTN_MISC] = deviceRecord->numButtons; deviceRecord->numButtons++; } } deviceRecord->axisStates = (float*)calloc(sizeof(float), deviceRecord->numAxes); deviceRecord->buttonStates = (bool*)calloc(sizeof(bool), deviceRecord->numButtons); Gamepad_eventDispatcher()->dispatchEvent(Gamepad_eventDispatcher(), GAMEPAD_EVENT_DEVICE_ATTACHED, deviceRecord); pthread_create(&deviceRecordPrivate->thread, NULL, deviceThread, deviceRecord); } } pthread_mutex_unlock(&devicesMutex); }
EventDispatcher * Gamepad_eventDispatcher() { if (eventDispatcher == NULL) { eventDispatcher = EventDispatcher_create(NULL); } return eventDispatcher; }
static void onDeviceMatched(void * context, IOReturn result, void * sender, IOHIDDeviceRef device) { CFArrayRef elements; CFIndex elementIndex; IOHIDElementRef element; CFStringRef cfProductName; struct Gamepad_device * deviceRecord; struct Gamepad_devicePrivate * hidDeviceRecord; IOHIDElementType type; char * description; struct Gamepad_queuedEvent queuedEvent; deviceRecord = malloc(sizeof(struct Gamepad_device)); deviceRecord->deviceID = nextDeviceID++; deviceRecord->vendorID = IOHIDDeviceGetVendorID(device); deviceRecord->productID = IOHIDDeviceGetProductID(device); deviceRecord->numAxes = 0; deviceRecord->numButtons = 0; deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord); devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1)); devices[numDevices++] = deviceRecord; hidDeviceRecord = malloc(sizeof(struct Gamepad_devicePrivate)); hidDeviceRecord->deviceRef = device; hidDeviceRecord->axisElements = NULL; hidDeviceRecord->buttonElements = NULL; deviceRecord->privateData = hidDeviceRecord; cfProductName = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); if (cfProductName == NULL || CFGetTypeID(cfProductName) != CFStringGetTypeID()) { description = malloc(strlen("[Unknown]" + 1)); strcpy(description, "[Unknown]"); } else { const char * cStringPtr; cStringPtr = CFStringGetCStringPtr(cfProductName, CFStringGetSmallestEncoding(cfProductName)); description = malloc(strlen(cStringPtr + 1)); strcpy(description, cStringPtr); } deviceRecord->description = description; elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); for (elementIndex = 0; elementIndex < CFArrayGetCount(elements); elementIndex++) { element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, elementIndex); type = IOHIDElementGetType(element); // All of the axis elements I've ever detected have been kIOHIDElementTypeInput_Misc. kIOHIDElementTypeInput_Axis is only included for good faith... if (type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis) { hidDeviceRecord->axisElements = realloc(hidDeviceRecord->axisElements, sizeof(struct HIDGamepadAxis) * (deviceRecord->numAxes + 1)); hidDeviceRecord->axisElements[deviceRecord->numAxes].cookie = IOHIDElementGetCookie(element); hidDeviceRecord->axisElements[deviceRecord->numAxes].logicalMin = IOHIDElementGetLogicalMin(element); hidDeviceRecord->axisElements[deviceRecord->numAxes].logicalMax = IOHIDElementGetLogicalMax(element); hidDeviceRecord->axisElements[deviceRecord->numAxes].hasNullState = !!IOHIDElementHasNullState(element); hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitch = IOHIDElementGetUsage(element) == kHIDUsage_GD_Hatswitch; hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitchSecondAxis = false; deviceRecord->numAxes++; if (hidDeviceRecord->axisElements[deviceRecord->numAxes - 1].isHatSwitch) { hidDeviceRecord->axisElements = realloc(hidDeviceRecord->axisElements, sizeof(struct HIDGamepadAxis) * (deviceRecord->numAxes + 1)); hidDeviceRecord->axisElements[deviceRecord->numAxes].isHatSwitchSecondAxis = true; deviceRecord->numAxes++; } } else if (type == kIOHIDElementTypeInput_Button) { hidDeviceRecord->buttonElements = realloc(hidDeviceRecord->buttonElements, sizeof(struct HIDGamepadButton) * (deviceRecord->numButtons + 1)); hidDeviceRecord->buttonElements[deviceRecord->numButtons].cookie = IOHIDElementGetCookie(element); deviceRecord->numButtons++; } } CFRelease(elements); deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes); deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons); IOHIDDeviceRegisterInputValueCallback(device, onDeviceValueChanged, deviceRecord); queuedEvent.dispatcher = Gamepad_eventDispatcher(); queuedEvent.eventType = GAMEPAD_EVENT_DEVICE_ATTACHED; queuedEvent.eventData = deviceRecord; if (deviceEventCount >= deviceEventQueueSize) { deviceEventQueueSize = deviceEventQueueSize == 0 ? 1 : deviceEventQueueSize * 2; deviceEventQueue = realloc(deviceEventQueue, sizeof(struct Gamepad_queuedEvent) * deviceEventQueueSize); } deviceEventQueue[deviceEventCount++] = queuedEvent; }
void Gamepad_detectDevices() { unsigned int numPadsSupported; unsigned int deviceIndex, deviceIndex2; JOYINFOEX info; JOYCAPS caps; bool duplicate; struct Gamepad_device * deviceRecord; struct Gamepad_devicePrivate * deviceRecordPrivate; UINT joystickID; int axisIndex; if (!inited) { return; } numPadsSupported = joyGetNumDevs(); for (deviceIndex = 0; deviceIndex < numPadsSupported; deviceIndex++) { info.dwSize = sizeof(info); info.dwFlags = JOY_RETURNALL; joystickID = JOYSTICKID1 + deviceIndex; if (joyGetPosEx(joystickID, &info) == JOYERR_NOERROR && joyGetDevCaps(joystickID, &caps, sizeof(JOYCAPS)) == JOYERR_NOERROR) { duplicate = false; for (deviceIndex2 = 0; deviceIndex2 < numDevices; deviceIndex2++) { if (((struct Gamepad_devicePrivate *) devices[deviceIndex2]->privateData)->joystickID == joystickID) { duplicate = true; break; } } if (duplicate) { continue; } deviceRecord = malloc(sizeof(struct Gamepad_device)); deviceRecord->deviceID = nextDeviceID++; deviceRecord->description = getDeviceDescription(joystickID, caps); deviceRecord->vendorID = caps.wMid; deviceRecord->productID = caps.wPid; deviceRecord->numAxes = caps.wNumAxes + ((caps.wCaps & JOYCAPS_HASPOV) ? 2 : 0); deviceRecord->numButtons = caps.wNumButtons; deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes); deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons); deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord); devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1)); devices[numDevices++] = deviceRecord; deviceRecordPrivate = malloc(sizeof(struct Gamepad_devicePrivate)); deviceRecordPrivate->joystickID = joystickID; deviceRecordPrivate->lastState = info; deviceRecordPrivate->xAxisIndex = 0; deviceRecordPrivate->yAxisIndex = 1; axisIndex = 2; deviceRecordPrivate->zAxisIndex = (caps.wCaps & JOYCAPS_HASZ) ? axisIndex++ : -1; deviceRecordPrivate->rAxisIndex = (caps.wCaps & JOYCAPS_HASR) ? axisIndex++ : -1; deviceRecordPrivate->uAxisIndex = (caps.wCaps & JOYCAPS_HASU) ? axisIndex++ : -1; deviceRecordPrivate->vAxisIndex = (caps.wCaps & JOYCAPS_HASV) ? axisIndex++ : -1; deviceRecordPrivate->axisRanges = malloc(sizeof(UINT[2]) * axisIndex); deviceRecordPrivate->axisRanges[0][0] = caps.wXmin; deviceRecordPrivate->axisRanges[0][1] = caps.wXmax; deviceRecordPrivate->axisRanges[1][0] = caps.wYmin; deviceRecordPrivate->axisRanges[1][1] = caps.wYmax; if (deviceRecordPrivate->zAxisIndex != -1) { deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][0] = caps.wZmin; deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][1] = caps.wZmax; } if (deviceRecordPrivate->rAxisIndex != -1) { deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][0] = caps.wRmin; deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][1] = caps.wRmax; } if (deviceRecordPrivate->uAxisIndex != -1) { deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][0] = caps.wUmin; deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][1] = caps.wUmax; } if (deviceRecordPrivate->vAxisIndex != -1) { deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][0] = caps.wVmin; deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][1] = caps.wVmax; } deviceRecordPrivate->povXAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1; deviceRecordPrivate->povYAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1; deviceRecord->privateData = deviceRecordPrivate; Gamepad_eventDispatcher()->dispatchEvent(Gamepad_eventDispatcher(), Atom_fromString(GAMEPAD_EVENT_DEVICE_ATTACHED), deviceRecord); } } }
Preferences * Preferences_create(const char * identifier) { stemobject_create_implementation(Preferences, init, identifier) } void Preferences_init(compat_type(Preferences *) selfPtr, const char * identifier) { Preferences * self = selfPtr; char * newIdentifier; StemObject_init(self); self->valueCount = 0; self->values = NULL; newIdentifier = malloc(strlen(identifier) + 1); strcpy(newIdentifier, identifier); self->identifier = newIdentifier; self->eventDispatcher = EventDispatcher_create(self); self->dispose = Preferences_dispose; self->addInteger = Preferences_addInteger; self->addFloat = Preferences_addFloat; self->addBoolean = Preferences_addBoolean; self->addString = Preferences_addString; self->addData = Preferences_addData; self->getInteger = Preferences_getInteger; self->getFloat = Preferences_getFloat; self->getBoolean = Preferences_getBoolean; self->getString = Preferences_getString; self->getData = Preferences_getData; self->setInteger = Preferences_setInteger; self->setFloat = Preferences_setFloat; self->setBoolean = Preferences_setBoolean;