dualsense-ts
Version:
The natural interface for your DualSense and DualSense Access controllers, with Typescript
78 lines • 2.94 kB
JavaScript
;
/**
* Audio device matching utilities for the DualSense controller.
*
* The DualSense registers as a USB Audio Class device (speaker + microphone)
* when connected over USB. These utilities help locate the corresponding
* audio devices in the Web Audio API or native audio libraries.
*
* Note: Audio devices are only available over USB, not Bluetooth.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DUALSENSE_AUDIO_LABELS = exports.DUALSENSE_AUDIO_PRODUCT_ID = exports.DUALSENSE_AUDIO_VENDOR_ID = void 0;
exports.findDualsenseAudioDevices = findDualsenseAudioDevices;
/** USB Vendor ID for Sony Interactive Entertainment */
exports.DUALSENSE_AUDIO_VENDOR_ID = 0x054c;
/** USB Product ID for the DualSense controller */
exports.DUALSENSE_AUDIO_PRODUCT_ID = 0x0ce6;
/**
* Known device label patterns for DualSense audio devices across platforms.
* Browser `enumerateDevices()` labels vary by OS:
* - Windows: "Wireless Controller"
* - macOS: "Wireless Controller"
* - Linux: "Wireless Controller" or "Sony Interactive Entertainment Wireless Controller"
*/
exports.DUALSENSE_AUDIO_LABELS = [
"Wireless Controller",
"DualSense",
];
/** Matches a MediaDeviceInfo label against known DualSense patterns */
function matchesDualsenseLabel(label) {
const lower = label.toLowerCase();
return exports.DUALSENSE_AUDIO_LABELS.some((pattern) => lower.includes(pattern.toLowerCase()));
}
/**
* Find DualSense audio devices using the Web Audio API.
*
* Requires `navigator.mediaDevices` (browser only). Returns matching
* audio input and output devices based on known label patterns.
*
* Note: Device labels may be empty until the user grants microphone
* or camera permission via `getUserMedia()`.
*
* @example
* ```typescript
* import { findDualsenseAudioDevices } from "dualsense-ts";
*
* const { outputs, inputs } = await findDualsenseAudioDevices();
* if (outputs.length > 0) {
* const ctx = new AudioContext({ sinkId: outputs[0].deviceId });
* // Route audio to the controller's speaker
* }
* if (inputs.length > 0) {
* const stream = await navigator.mediaDevices.getUserMedia({
* audio: { deviceId: { exact: inputs[0].deviceId } },
* });
* // Capture from the controller's microphone
* }
* ```
*/
async function findDualsenseAudioDevices() {
if (typeof navigator === "undefined" ||
!navigator.mediaDevices?.enumerateDevices) {
return { outputs: [], inputs: [] };
}
const devices = await navigator.mediaDevices.enumerateDevices();
const outputs = [];
const inputs = [];
for (const device of devices) {
if (!matchesDualsenseLabel(device.label))
continue;
if (device.kind === "audiooutput")
outputs.push(device);
else if (device.kind === "audioinput")
inputs.push(device);
}
return { outputs, inputs };
}
//# sourceMappingURL=audio.js.map