Skip to content

SDK event system ​

Event names use colon notation, such as playback:trackChanged. Method invocations use dot notation, such as playback.play.

Subscribe ​

javascript
// Subscribe and retain the returned unsubscribe function.
const unsubscribe = fb.on('playback:trackChanged', (track) => {
    console.log('Now playing:', track.title);
});

// Unsubscribe.
unsubscribe();

Subscribe once ​

javascript
fb.once('playback:trackChanged', (track) => {
    console.log('First track:', track.title);
});

Unsubscribe ​

javascript
// Preferred: call the function returned by fb.on().
const unsub = fb.on('playback:time', handler);
unsub();

// Alternatively, remove the same handler explicitly.
fb.on('playback:time', handler);
fb.off('playback:time', handler);

Playback events ​

EventEmitted whenPayload
playback:trackChangedThe current track changesPlaybackTrackChangedPayload
playback:stateChangedPlayback state changes{ state, position?, duration? }
playback:pausedPause state changes{ paused }
playback:stoppedPlayback stops{ reason }
playback:startingPlayback is about to start{ command, paused? }
playback:seekedPlayback position is changed{ position }
playback:volumeChangedVolume or mute state changes{ volume, volumeDb, muted, isMuted }
playback:timeThe normal-resolution position updates{ position }
playback:timeHighResThe high-resolution position updates{ position }
playback:orderChangedPlayback order changes{ orderIndex, order }
playback:queueChangedPlayback queue changes{ origin }
playback:editedCurrent-track metadata changesPlaybackEditedPayload
playback:dynamicInfoStream information changes{ bitrate, streamTitle? }
playback:dynamicInfoTrackDynamic stream-track metadata changes{ artist?, title? }
playback:itemPlayedA track finishes playingPlaybackItemPlayedPayload
playback:stopAfterCurrentChangedStop-after-current changes{ enabled }
playback:followCursorChangedPlayback-follow-cursor changes{ enabled }
playback:cursorFollowChangedCursor-follow-playback changes{ enabled }

Playlist events ​

EventEmitted whenPayload
playlist:activatedActive playlist changes{ oldIndex, newIndex }
playlist:createdA playlist is created{ index, name }
playlist:removedA playlist is removed{ oldCount, newCount }
playlist:renamedA playlist is renamed{ index, name }
playlist:reorderedPlaylist order changes{ count }
playlist:lockChangedPlaylist lock state changes{ playlist, locked }
playlist:itemsAddedItems are added{ playlist, start, count }
playlist:itemsRemovedItems are removed{ playlist, oldCount, newCount }
playlist:itemsReorderedItems are reordered{ playlist, count }
playlist:itemsReplacedItems are replaced{ playlist, count }
playlist:selectionChangedSelection changes{ playlist }
playlist:focusChangedFocused item changes{ playlist, from, to }
playlist:defaultFormatChangedDefault formatting changesEmpty object
playlist:addCompleteAn asynchronous add completes{ operationId, success, addedCount, totalCount }

Library, metadata, and selection events ​

EventEmitted whenPayload
library:itemsAddedLibrary items are added{ count, timestamp }
library:itemsRemovedLibrary items are removed{ count, timestamp }
library:itemsModifiedLibrary items are modified{ count, timestamp }
library:initializedLibrary initialization completes{ timestamp }
library:getAllResultAn asynchronous library.getAll result is readyLibraryGetAllResultPayload
metadata:writeCompleteAn asynchronous metadata write completesMetadataWriteCompletePayload
metadata:probeProgressA batch of metadata.probeBatchAsync results is readyMetadataProbeProgressPayload
metadata:probeCompleteAn asynchronous batch probe finishes, is cancelled, or failsMetadataProbeCompletePayload
metadb:changedMetadata changes{ tracks, count, fromHook, timestamp }
selection:changedGlobal selection changes{ count, type, handles, truncated, track, nowPlaying }

Audio events ​

EventEmitted whenPayload
audio:spectrumSubscribed spectrum data updates{ spectrum, fftSize?, bands? }
audio:streamSubscribed audio-stream data updatesCurrently typed as an empty object
audio:dspPresetChangedDSP preset changesEmpty object
audio:outputDeviceChangedOutput device changesEmpty object
audio:replaygainModeChangedReplayGain mode changes{ mode }
audio:fullWaveformReadyFull-waveform generation completesAudioFullWaveformReadyPayload
audio:fullWaveformFailedFull-waveform generation fails{ taskId, path, error, code }

Window, panel, UI, and desktop events ​

EventEmitted whenPayload
window:alwaysOnTopChangedAlways-on-top changes{ enabled }
window:stateChangedWindow state changesCanonical isMaximized, isMinimized, isActive, and isFullscreen fields plus compatibility aliases
window:popupOpenedA popup opens{ windowId, title, url }
window:popupClosedA popup closes{ windowId }
window:beforeCloseClose confirmation is requested{ windowId }
window:messageA cross-window message arrives{ sourceWindowId, message }
window:behaviorChangedPopup behavior changes{ windowId, profile, behavior, resolvedBehavior }
window:minimizeSuppressedA minimize action is suppressed{ windowId, reason }
window:backdropStateChangedA backdrop activation policy is applied{ windowId, active, mode, effect }
window:hoverStateChangedWindow hover state changes{ windowId, reason?, hovering? }
panel:initializedPanel initialization completesPanelInitializedPayload
panel:focus / panel:blurPanel focus changesEmpty object
panel:visibilityChangedDUI panel visibility changes{ visible }
panel:configChangedPanel configuration changesPanelConfigChangedPayload
ui:coloursChanged / ui:fontChangedUI colors or fonts changeUnspecified object
ui:menuItemClickedA UI menu item is clicked{ id, label }
ui:toastA toast is requested{ message, duration, type, position }
system:themeChangedSystem theme changes{ darkMode }
cursor:hiddenChangedCursor hidden state changesCursorHiddenChangedPayload
taskbar:buttonClickedA taskbar button is clicked{ id }
webview:processFailedA WebView process fails or recovers{ kind, kindRaw, recovered, recoveryAction }

Tray events ​

The tray icon is application-scoped and has no source window. Its events are broadcast to all windows.

EventEmitted whenPayload
tray:clickThe tray icon is clicked{ button, x, y }
tray:doubleClickThe tray icon is double-clicked{ x, y }
tray:beforeContextMenuBefore the context menu opens{ x, y }
tray:menuItemClickedAn ordinary tray item is selected or a rich value changes{ id, value? }

Ordinary user items and now-playing cards report { id } and close the menu. Rich value controls report { id, value } and keep it open: ratings use 0..5, sliders use an integer in [min, max], and segmented controls use the selected zero-based index. Built-in showPlaybackControls / showSystemItems injections and items declaring playbackAction execute natively and do not fire this event.

Application, keyboard, and menu events ​

EventEmitted whenPayload
app:beforeQuitfoobar2000 is about to quitEmpty object
keyboard:hotkeyA registered hotkey fires{ id, key, action }
menu:showA custom menu opens{ menuId }
menu:selectA custom-menu item is selected{ menuId, itemId }
menu:valueChangedA rating, slider, or segmented control in a custom menu changes value; the menu stays open{ menuId, itemId, value }
menu:dismissA custom menu closes{ menuId, reason }

Cross-window events ​

EventEmitted whenPayload
port:connectedA named port connects{ portId, name, windowId }
port:disconnectedA named port disconnects{ portId, name, windowId }
port:messageA port message arrives{ portId, sourcePortId, sourceWindowId, message }
state:changedShared state changes{ key, value, previousValue, sourceWindowId, expiresAt? }
state:deletedShared state is removed or expires{ key, sourceWindowId, reason }

File operation events ​

EventEmitted whenPayload
file:opProgressA batch of file.copyAsync / moveAsync / deleteAsync results is readyFileOpProgressPayload
file:opCompleteAn asynchronous file operation finishes or is cancelledFileOpCompletePayload

Both go to the window that started the operation, so their results may carry real paths. Once that window is gone the host cannot resolve it any more and the event falls back to the main instance, or is dropped when that instance has no WebView attached; see cancelOp() for when trailing events can still appear. Progress is batched at 64 entries or 100 ms, whichever comes first, and the final partial batch always precedes file:opComplete.

Plugin, HTTP, and JIT queue events ​

EventEmitted whenPayload
plugin:registered / plugin:unregisteredAn external plugin is registered or removedPluginRegisteredPayload / PluginUnregisteredPayload
api:registered / api:unregisteredAn external API is registered or removedApiRegisteredPayload / ApiUnregisteredPayload
http:responseAn asynchronous HTTP request completesHttpResponsePayload
http:downloadCompleteA download completesHttpDownloadCompletePayload
jitQueue:needNextThe host requests the next item{ currentTrackId, reason }
jitQueue:trackChangedThe JIT queue's current track changes{ trackId, title }
jitQueue:listExhaustedThe JIT queue buffer is exhausted{ lastTrackId }
jitQueue:preloadCompleteJIT preloading completesJitQueuePreloadCompletePayload
jitQueue:errorA JIT queue item fails{ trackId, error, url? or path? }

Host events are also dispatched as fb2k:* DOM CustomEvent instances.

See the event-system reference for the complete payload reference. SMP event-name mappings are documented in the SMP compatibility layer.