Docs
/

@leumas/devices

The shared device layer. Today: the browser half — enumerating media devices, the ONE permission latch a denied prompt sets, camera streams that are ref-counted and time-out on a hung prompt, a mic...

@leumas/devices

The shared device layer behind Studio's Devices HUD (/admin/devices).

Today it ships the browser half — everything a surface needs to list, open, test and capture the cameras, microphones and speakers attached to the machine the browser is running on. Nothing in it talks to an API.

Why it exists

Three copies of "enumerate the media devices" were already in the tree, each grouping, labelling and failing slightly differently, so the same machine described itself differently depending on which surface you opened:

WasNow
products/leumas-studio/src/admin/surveillance/utils/browserCamera.jsa re-export shim over ./media/camera.js
shared/packages/os/src/apps/device-manager/DeviceManager.jsxconsumes useMediaDevices()
shared/packages/splats/src/capture/recorder.jsgeneralised into ./media/recorder.js

@leumas/sing's createMicSource keeps its own latch: it is bound to Sing's AudioContext lifecycle and its game loop, and prising that apart would be a refactor of a working game for no visible gain. What is shared here is the rule, not the plumbing.

The one rule

A refused permission LATCHES OFF. A denied getUserMedia can never be fixed by asking again — the browser remembers the decision — so a surface that re-requests on the next render prompts forever. permission.js holds a sticky per-kind denied state that only retryMedia(kind) clears, and it must be called from a real click. This has shipped as a live defect in this repo before.

API

import {
  useMediaDevices,          // cameras/microphones/speakers + `devicechange` + needsPermission
  useMicLevel,              // RMS meter for one mic; tears down track, node and AudioContext
  requestMedia, retryMedia, stopStream, describeMediaError,   // the latch
  listCameraDevices, startBrowserCamera, stopBrowserCamera, captureFrame,
  isRecordingSupported, startRecording, downloadBlob, stamp,
} from '@leumas/devices/media';

import { TRANSPORTS, SIDES, STATES, isPresent } from '@leumas/devices';

The barrel exports nothing from ./media on purpose: that half is React and browser-only, and a Node consumer (a guard, the API, a test) importing the barrel must not be handed navigator.

Traps worth knowing

  • Before any grant, enumerateDevices() returns the right number of devices with **empty labels

and empty ids**. Nothing is broken — the browser is refusing to fingerprint you. needsPermission is the tell; ensureLabels() asks once, through the latch, and stops the probe stream immediately.

  • getUserMedia never settles while a prompt sits unanswered, so caching the pending promise (to

share one camera between tiles) makes a hung prompt immortal. camera.js races it against a 15s timeout for that reason alone.

  • A preview holds the camera open. Stop every track on unmount or the recording light stays on and

the next app to ask is told the device is busy.

  • setSinkId (routing audio to a chosen output) is Chromium-only. Show it disabled with a

reason rather than hiding it.

  • useMicLevel measures RMS, not peak: a peak meter pins to 1.0 on the first consonant and says

"working" for a mic that has picked up one click and gone silent.

Next

Pass 4 of the Devices roadmap adds the isomorphic half to the barrel — the device record, defineDeviceDriver, defineDeviceProvider — plus a ./host subpath for the machine-local reads (ports, adapters, the paired Bluetooth list) that only mount under caps.localHardware.

What it exports

166 exports: 35 components, 2 hooks, 129 helpers. Import from @leumas/devices.

AGGREGATESAUDIO_SERVICESBAUD_RATESCAPABILITY_RECHANNEL_TYPESCHANNELS_PER_MUXCODE_ALIASESDEFAULT_DEADLINE_MSDEFAULT_ENTRY_LIMITDEFAULT_LIMITSDEFAULT_MAX_DEPTHDRIVE_KINDSEEPROM_WRITINGEMPTY_CODEEMPTY_LAYOUTFALLBACK_MSIDLE_MSIS_MACIS_WINMAX_LINE_BYTESMQTT_INSTALL_HINTMUX_COUNTOFFLINE_MSOUTPUTSOVERFLOW_MODESPROBE_PORTSPROBE_TIMEOUT_MSRAW_MAXRAW_MINRULE_SAFESEMANTIC_TYPESSIDESSSDP_AUDIO_TARGETSSTATESTRANSPORTSuseMediaDevicesuseMicLeveladapterThroughputapplyCalibrationarpNeighboursbleDriverbuildSizeTreecapabilitiesFromLayoutcapabilityIdcaptureFramecaptureFrameToBlobchannelsOfconvertTemperaturecreateDeviceRegistrycreateGroboticsSessioncreateGroboticsWsListenercreateLineSplittercreateRecorderdecodeFramedecodeLinedecodeReadingdefineDeviceDriverdefineDeviceProviderdescribeBrowserCameraErrordescribeBrowserMicErrordescribeMediaErrordescribeScreenShareErrordiffLayoutsdiscoverdownloadBlobencodeQueryfakeClockfromLegacySetupgetBrowserDrivergetConfiggetMediaErrorgetMediaStategoodbyeInstancesgroboticsSerialDriverhasWebBluetoothhasWebHidhasWebSerialisChromiumisPresentisPrivateIpv4isRandomizedMacisRecordingSupportedisScreenShareSupportedisSecurekillPortlabelDriftlayoutHashlayoutWarningslistAdapterslistAudioInputsAsynclistAudioOutputslistAudioOutputsAsynclistBrowserDriverslistCameraDeviceslistMicDeviceslistPortslistVolumeslocalSubnetsmapRawToPercentmdnsListenmdnsProbemockTransportmqttDrivernetworkSnapshotnormalizeDevicenormalizeLayoutnormalizeLayoutsnormalizeReadingonMediaStateouiVendorpairedBluetoothpairedBluetoothAsyncparseAnswersparseCapabilityIdparsePactlpauseStreampidsOnPortpingplatformWarningspresenceOfpreviouslyPermittedBluetoothpsJsonrawToMilliCelsiusreadCharacteristicreadNameregisterBrowserDriverrequestMediaretryMediarouteInforunsanitizeDevicesaveThresholdsscaleReadingscansendIrserialDriverserialTransportsetConfigsetOutputsetThresholdshapeBluetoothshapeWindowsshouldIgnorespawnAsyncssdpListenssdpProbestampstartBrowserCamerastartBrowserMicstartRecordingstartScreenSharestopBrowserCamerastopBrowserMicstopScreenSharestopStreamstreamsupportsCanvasFiltertopicMatchestypeForCodetypeForSemantictypeForWireunavailableReasonwatchAudioDeviceswindowsLabelwirelessStatuswritesEeprom
Source shared/packages/devices/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt