bool MidiDriver::checkDevice(MidiDriver::DeviceHandle handle) { const MusicPlugin::List p = MusicMan.getPlugins(); for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) return (**m)->checkDevice(handle); } return false; }
MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) { MidiDriver *driver = 0; const MusicPlugin::List p = MusicMan.getPlugins(); for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) (**m)->createInstance(&driver, handle); } return driver; }
OSString* Xbox360ControllerClass::newProductString() const { OSString *retString = getDeviceString(GetOwnerProvider(this)->GetProductStringIndex()); if (retString->isEqualTo("Controller")) { retString->release(); return OSString::withCString("Xbox 360 Wired Controller"); } else { return retString; } }
OSString* Xbox360ControllerClass::newSerialNumberString() const { return getDeviceString(GetOwnerProvider(this)->GetSerialNumberStringIndex()); }
OSString* Xbox360ControllerClass::newManufacturerString() const { return getDeviceString(GetOwnerProvider(this)->GetManufacturerStringIndex()); }
MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) { // Query the selected music device (defaults to MT_AUTO device). Common::String selDevStr = ConfMan.hasKey("music_driver") ? ConfMan.get("music_driver") : Common::String("auto"); DeviceHandle hdl = getDeviceHandle(selDevStr.empty() ? Common::String("auto") : selDevStr); DeviceHandle reslt = 0; _forceTypeMT32 = false; // Check whether the selected music driver is compatible with the // given flags. switch (getMusicType(hdl)) { case MT_PCSPK: if (flags & MDT_PCSPK) reslt = hdl; break; case MT_PCJR: if (flags & MDT_PCJR) reslt = hdl; break; case MT_CMS: if (flags & MDT_CMS) reslt = hdl; break; case MT_ADLIB: if (flags & MDT_ADLIB) reslt = hdl; break; case MT_C64: if (flags & MDT_C64) reslt = hdl; break; case MT_AMIGA: if (flags & MDT_AMIGA) reslt = hdl; break; case MT_APPLEIIGS: if (flags & MDT_APPLEIIGS) reslt = hdl; break; case MT_TOWNS: if (flags & MDT_TOWNS) reslt = hdl; break; case MT_PC98: if (flags & MDT_PC98) reslt = hdl; break; case MT_GM: case MT_GS: case MT_MT32: if (flags & MDT_MIDI) reslt = hdl; break; case MT_NULL: reslt = hdl; break; default: break; } Common::String failedDevStr; if (getMusicType(hdl) == MT_INVALID) { // If the expressly selected driver or device cannot be found (no longer compiled in, turned off, etc.) // we display a warning and continue. failedDevStr = selDevStr; Common::String warningMsg = Common::String::format(_("The selected audio device '%s' was not found (e.g. might be turned off or disconnected)."), failedDevStr.c_str()) + " " + _("Attempting to fall back to the next available device..."); GUI::MessageDialog dialog(warningMsg); dialog.runModal(); } MusicType tp = getMusicType(reslt); if (tp != MT_INVALID && tp != MT_AUTO) { if (checkDevice(reslt)) { return reslt; } else { // If the expressly selected device cannot be used we display a warning and continue. failedDevStr = getDeviceString(hdl, MidiDriver::kDeviceName); Common::String warningMsg = Common::String::format(_("The selected audio device '%s' cannot be used. See log file for more information."), failedDevStr.c_str()) + " " + _("Attempting to fall back to the next available device..."); GUI::MessageDialog dialog(warningMsg); dialog.runModal(); } } // If the selected driver did not match the flags setting, // we try to determine a suitable and "optimal" music driver. const MusicPlugin::List p = MusicMan.getPlugins(); // If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be // detected since they are hard coded and cannot be disabled). bool skipMidi = !(flags & (MDT_PREFER_GM | MDT_PREFER_MT32)); while (flags != MDT_NONE) { if ((flags & MDT_MIDI) && !skipMidi) { // If a preferred MT32 or GM device has been selected that device gets returned if available. Common::String devStr; if (flags & MDT_PREFER_MT32) devStr = ConfMan.hasKey("mt32_device") ? ConfMan.get("mt32_device") : Common::String("null"); else if (flags & MDT_PREFER_GM) devStr = ConfMan.hasKey("gm_device") ? ConfMan.get("gm_device") : Common::String("null"); else devStr = "auto"; // Default to Null device here, since we also register a default null setting for // the MT32 or GM device in the config manager. hdl = getDeviceHandle(devStr.empty() ? Common::String("null") : devStr); const MusicType type = getMusicType(hdl); // If we have a "Don't use GM/MT-32" setting we skip this part and jump // to AdLib, PC Speaker etc. detection right away. if (type != MT_NULL) { if (type == MT_INVALID) { // If the preferred (expressly requested) selected driver or device cannot be found (no longer compiled in, turned off, etc.) // we display a warning and continue. Don't warn about the missing device if we did already (this becomes relevant if the // missing device is selected as preferred device and also as GM or MT-32 device). if (failedDevStr != devStr) { Common::String warningMsg = Common::String::format(_("The preferred audio device '%s' was not found (e.g. might be turned off or disconnected)."), devStr.c_str()) + " " + _("Attempting to fall back to the next available device..."); GUI::MessageDialog dialog(warningMsg); dialog.runModal(); } } else if (type != MT_AUTO) { if (checkDevice(hdl)) { if (flags & MDT_PREFER_MT32) // If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h). _forceTypeMT32 = true; return hdl; } else { // If the preferred (expressly requested) device cannot be used we display a warning and continue. // Don't warn about the failing device if we did already (this becomes relevant if the failing // device is selected as preferred device and also as GM or MT-32 device). if (failedDevStr != getDeviceString(hdl, MidiDriver::kDeviceName)) { Common::String warningMsg = Common::String::format(_("The preferred audio device '%s' cannot be used. See log file for more information."), getDeviceString(hdl, MidiDriver::kDeviceName).c_str()) + " " + _("Attempting to fall back to the next available device..."); GUI::MessageDialog dialog(warningMsg); dialog.runModal(); } } } // If no specific device is selected (neither in the scummvm nor in the game domain) // and there is no preferred MT32 or GM device selected either or if the detected device is unavailable we arrive here. // If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator). if (flags & MDT_PREFER_MT32) { for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { MusicDevices i = (**m)->getDevices(); for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { if (d->getMusicType() == MT_MT32) { hdl = d->getHandle(); if (checkDevice(hdl)) return hdl; } } } } // Now we default to the first available device with music type 'MT_GM' if not // MT-32 is preferred or if MT-32 is preferred but all other devices have failed. if (!(flags & MDT_PREFER_MT32) || flags == (MDT_PREFER_MT32 | MDT_MIDI)) { for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { MusicDevices i = (**m)->getDevices(); for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) { hdl = d->getHandle(); if (checkDevice(hdl)) return hdl; } } } // Detection flags get removed after final detection attempt to avoid further attempts. flags &= ~(MDT_MIDI | MDT_PREFER_GM | MDT_PREFER_MT32); } } } // The order in this list is important, since this is the order of preference // (e.g. MT_ADLIB is checked before MT_PCJR and MT_PCSPK for a good reason). // Detection flags get removed after detection attempt to avoid further attempts. if (flags & MDT_TOWNS) { tp = MT_TOWNS; flags &= ~MDT_TOWNS; } else if (flags & MDT_PC98) { tp = MT_PC98; flags &= ~MDT_PC98; } else if (flags & MDT_ADLIB) { tp = MT_ADLIB; flags &= ~MDT_ADLIB; } else if (flags & MDT_PCJR) { tp = MT_PCJR; flags &= ~MDT_PCJR; } else if (flags & MDT_PCSPK) { tp = MT_PCSPK; flags &= ~MDT_PCSPK; } else if (flags & MDT_C64) { tp = MT_C64; flags &= ~MDT_C64; } else if (flags & MDT_AMIGA) { tp = MT_AMIGA; flags &= ~MDT_AMIGA; } else if (flags & MDT_APPLEIIGS) { tp = MT_APPLEIIGS; flags &= ~MDT_APPLEIIGS; } else if (flags & MDT_MIDI) { // If we haven't tried to find a MIDI device yet we do this now. skipMidi = false; continue; } else if (flags) { // Invalid flags. Set them to MDT_NONE to leave detection loop. flags = MDT_NONE; tp = MT_AUTO; } for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { MusicDevices i = (**m)->getDevices(); for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { if (d->getMusicType() == tp) { hdl = d->getHandle(); if (checkDevice(hdl)) return hdl; } } } } return 0; }
bool JoystickImpl::open(unsigned int index) { m_index = index; Location deviceLoc = m_locationIDs[index]; // The device we need to load // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices == NULL) return false; // Get a usable copy of the joysticks devices. CFIndex joysticksCount = CFSetGetCount(devices); CFTypeRef devicesArray[joysticksCount]; CFSetGetValues(devices, devicesArray); // Get the desired joystick. IOHIDDeviceRef self = 0; for (CFIndex i(0); i < joysticksCount; ++i) { IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; if (deviceLoc == HIDInputManager::getLocationID(d)) { self = d; break; // We found it so we stop looping. } } if (self == 0) { // This shouldn't happen! CFRelease(devices); return false; } m_identification.name = getDeviceString(self, CFSTR(kIOHIDProductKey), m_index); m_identification.vendorId = getDeviceUint(self, CFSTR(kIOHIDVendorIDKey), m_index); m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey), m_index); // Get a list of all elements attached to the device. CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, NULL, kIOHIDOptionsTypeNone); if (elements == NULL) { CFRelease(devices); return false; } // How many elements are there? CFIndex elementsCount = CFArrayGetCount(elements); if (elementsCount == 0) { // What is a joystick with no element? CFRelease(elements); CFRelease(devices); return false; } // Go through all connected elements. for (int i = 0; i < elementsCount; ++i) { IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); switch (IOHIDElementGetType(element)) { case kIOHIDElementTypeInput_Misc: switch (IOHIDElementGetUsage(element)) { case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break; case kHIDUsage_GD_Y: m_axis[Joystick::Y] = element; break; case kHIDUsage_GD_Z: m_axis[Joystick::Z] = element; break; case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break; case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break; case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break; // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored. } break; case kIOHIDElementTypeInput_Button: if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot... m_buttons.push_back(element); // ...we add this element to the list // Else: too many buttons. We ignore this one. break; default: // Make compiler happy break; } } // Ensure that the buttons will be indexed in the same order as their // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate); // Note: Joy::AxisPovX/Y are not supported (yet). // Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test. // Retain all these objects for personal use for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) CFRetain(*it); for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) CFRetain(it->second); // Note: we didn't retain element in the switch because we might have multiple // Axis X (for example) and we want to keep only the last one. So to prevent // leaking we retain objects 'only' now. CFRelease(devices); CFRelease(elements); return true; }
bool JoystickImpl::open(unsigned int index) { m_index = index; m_hat = NULL; Location deviceLoc = m_locationIDs[index]; // The device we need to load // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices == NULL) return false; // Get a usable copy of the joysticks devices. CFIndex joysticksCount = CFSetGetCount(devices); CFTypeRef devicesArray[joysticksCount]; CFSetGetValues(devices, devicesArray); // Get the desired joystick. IOHIDDeviceRef self = 0; for (CFIndex i(0); self == 0 && i < joysticksCount; ++i) { IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; if (deviceLoc == HIDInputManager::getLocationID(d)) self = d; } if (self == 0) { CFRelease(devices); return false; } m_identification.name = getDeviceString(self, CFSTR(kIOHIDProductKey), m_index); m_identification.vendorId = getDeviceUint(self, CFSTR(kIOHIDVendorIDKey), m_index); m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey), m_index); // Get a list of all elements attached to the device. CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, NULL, kIOHIDOptionsTypeNone); if (elements == NULL) { CFRelease(devices); return false; } // Go through all connected elements. CFIndex elementsCount = CFArrayGetCount(elements); for (int i = 0; i < elementsCount; ++i) { IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); switch (IOHIDElementGetUsagePage(element)) { case kHIDPage_GenericDesktop: switch (IOHIDElementGetUsage(element)) { case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break; case kHIDUsage_GD_Y: m_axis[Joystick::Y] = element; break; case kHIDUsage_GD_Z: m_axis[Joystick::Z] = element; break; case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break; case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break; case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break; case kHIDUsage_GD_Hatswitch: // From §4.3 MiscellaneousControls of HUT v1.12: // // > Hat Switch: // > A typical example is four switches that are capable of generating // > information about four possible directions in which the knob can be // > tilted. Intermediate positions can also be decoded if the hardware // > allows two switches to be reported simultaneously. // // We assume this model here as well. Hence, with 4 switches and intermediate // positions we have 8 values (0-7) plus the "null" state (8). { CFIndex min = IOHIDElementGetLogicalMin(element); CFIndex max = IOHIDElementGetLogicalMax(element); if (min != 0 || max != 7) { sf::err() << std::hex << "Joystick (vendor/product id: 0x" << m_identification.vendorId << "/0x" << m_identification.productId << std::dec << ") range is an unexpected one: [" << min << ", " << max << "]" << std::endl; } else { m_hat = element; } } break; case kHIDUsage_GD_GamePad: // We assume a game pad is an application collection, meaning it doesn't hold // any values per say. They kind of "emit" the joystick's usages. // See §3.4.3 Usage Types (Collection) of HUT v1.12 if (IOHIDElementGetCollectionType(element) != kIOHIDElementCollectionTypeApplication) { sf::err() << std::hex << "Gamepage (vendor/product id: 0x" << m_identification.vendorId << "/0x" << m_identification.productId << ") is not an CA but a 0x" << IOHIDElementGetCollectionType(element) << std::dec << std::endl; } break; default: #ifdef SFML_DEBUG sf::err() << "Unexpected usage for element of Page Generic Desktop: 0x" << std::hex << IOHIDElementGetUsage(element) << std::dec << std::endl; #endif break; } break; case kHIDPage_Button: if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot... m_buttons.push_back(element); // ...we add this element to the list // Else: too many buttons. We ignore this one. break; default: /* No other page is expected because of the mask applied by the HID manager. */ break; } } // Ensure that the buttons will be indexed in the same order as their // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate); // Retain all these objects for personal use for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) CFRetain(*it); for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) CFRetain(it->second); if (m_hat != NULL) CFRetain(m_hat); // Note: we didn't retain element in the switch because we might have multiple // Axis X (for example) and we want to keep only the last one. To prevent // leaking we retain objects 'only' now. CFRelease(devices); CFRelease(elements); return true; }