foo-webview-sdk
    Preparing search index...

    Variable fbConst

    fb: {
        ApiCallError: typeof ApiCallError;
        artwork: {
            getAvailableArtwork: (
                path: string,
            ) => Promise<ArtworkGetAvailableArtworkResponse>;
            getAvailableTypes: (
                path?: string,
            ) => Promise<ArtworkGetAvailableTypesResponse>;
            getBatch: (
                paths: string[],
                type?: AlbumArtType,
            ) => Promise<ArtworkGetBatchResponse>;
            getByPath: (
                path: string,
                type?: AlbumArtType,
            ) => Promise<ArtworkGetByPathResponse>;
            getByPlaylistItem: (
                playlist: PlaylistRef,
                index: number,
                type?: AlbumArtType,
            ) => Promise<ArtworkGetByPlaylistItemResponse>;
            getCurrent: (type?: AlbumArtType) => Promise<ArtworkGetCurrentResponse>;
            getFb2kUrl: (
                type?: AlbumArtType,
                options?: Pick<ArtworkGetFb2kUrlParams, "maxSize">,
            ) => Promise<ArtworkGetFb2kUrlResponse>;
            getFb2kUrlByPath: (
                path: string,
                type?: AlbumArtType,
                options?: Pick<ArtworkGetFb2kUrlByPathParams, "maxSize">,
            ) => Promise<ArtworkGetFb2kUrlByPathResponse>;
            getFb2kUrlByPathBatch: (
                items: string[] | ArtworkBatchItem[],
                opts?: { maxSize?: number; type?: AlbumArtType },
            ) => Promise<ArtworkGetFb2kUrlByPathBatchResponse>;
            getFolderImages: (
                directory: string,
            ) => Promise<ArtworkGetFolderImagesResponse>;
            getForTrack: (
                path: string,
                type?: AlbumArtType,
                options?: ArtworkOptions,
            ) => Promise<ArtworkGetForTrackResponse>;
            getLyrics: (path?: string) => Promise<ArtworkGetLyricsResponse>;
            getMetadata: (path?: string) => Promise<ArtworkGetMetadataResponse>;
            withMaxSize: (url: string, maxSize?: number) => string;
        };
        audio: {
            analyzeBPM: (path: string) => Promise<AudioAnalyzeBPMResponse>;
            cancelDecodePcm: (taskId: string) => Promise<AudioCancelDecodePcmResponse>;
            cancelFullWaveform: (
                taskId: string,
            ) => Promise<AudioCancelFullWaveformResponse>;
            decodePcm: (path: string, opts?: DecodePcmOptions) => Promise<PcmBuffer>;
            generateFullWaveform: (
                path: string,
                opts?: FullWaveformOptions & { signal?: AbortSignal; timeout?: number },
            ) => Promise<FullWaveformResult>;
            getOutputInfo: () => Promise<AudioGetOutputInfoResponse>;
            getPcmDebugState: () => Promise<AudioGetPcmDebugStateResponse>;
            getSpectrum: (
                options?: AudioGetSpectrumParams,
            ) => Promise<AudioGetSpectrumResponse>;
            getSpectrumDebugState: () => Promise<AudioGetSpectrumDebugStateResponse>;
            getStreamInfo: () => Promise<AudioGetStreamInfoResponse>;
            getWaveform: (
                pathOrOpts?: string | AudioGetWaveformParams,
                opts?: AudioGetWaveformParams,
            ) => Promise<AudioGetWaveformResponse>;
            isVisualizationAvailable: () => Promise<
                AudioIsVisualizationAvailableResponse,
            >;
            setChannelMode: (
                mode: NonNullable<"default" | "back" | "front" | "mono" | undefined>,
            ) => Promise<AudioSetChannelModeResponse>;
            subscribeSpectrum: SpectrumSubscribeFunction;
            subscribeStream: (opts?: PcmStreamOptions) => PcmStream;
            unsubscribeStream: (
                subscriptionId?: string,
            ) => Promise<AudioUnsubscribeStreamResponse>;
        };
        canPlay: (
            track: ContainerTrack,
            limits?: MediaVideoDecodingLimits,
        ) => Promise<MediaCanPlayResult>;
        clipboard: {
            read: () => Promise<ClipboardReadResponse>;
            write: (text: string) => Promise<ClipboardWriteResponse>;
            writeFiles: (paths: string[]) => Promise<ClipboardWriteFilesResponse>;
            writeHTML: (
                html: string,
                plainText?: string,
            ) => Promise<ClipboardWriteHTMLResponse>;
        };
        config: {
            export: () => Promise<ConfigExportResponse>;
            get: (key: string, defaultValue?: JsonValue) => Promise<ConfigGetResponse>;
            getActiveDspPreset: () => Promise<ConfigGetActiveDspPresetResponse>;
            getAdvancedConfig: (
                parentGuid?: string,
            ) => Promise<ConfigGetAdvancedConfigResponse>;
            getAdvancedConfigValue: (
                guid: string,
            ) => Promise<ConfigGetAdvancedConfigValueResponse>;
            getAll: () => Promise<ConfigGetAllResponse>;
            getComponents: () => Promise<ConfigGetComponentsResponse>;
            getCursorFollowPlayback: () => Promise<
                ConfigGetCursorFollowPlaybackResponse,
            >;
            getDspPresets: () => Promise<ConfigGetDspPresetsResponse>;
            getLibraryFilePatterns: () => Promise<
                ConfigGetLibraryFilePatternsResponse,
            >;
            getLibraryStatus: () => Promise<ConfigGetLibraryStatusResponse>;
            getOutputConfig: () => Promise<ConfigGetOutputConfigResponse>;
            getOutputDevices: () => Promise<ConfigGetOutputDevicesResponse>;
            getPlaybackFollowCursor: () => Promise<
                ConfigGetPlaybackFollowCursorResponse,
            >;
            getPreferencesPages: () => Promise<ConfigGetPreferencesPagesResponse>;
            getPreferencesStandardGuids: () => Promise<
                ConfigGetPreferencesStandardGuidsResponse,
            >;
            getReplaygainMode: () => Promise<ConfigGetReplaygainModeResponse>;
            getVersionInfo: () => Promise<ConfigGetVersionInfoResponse>;
            remove: (key: string) => Promise<ConfigRemoveResponse>;
            resetAdvancedConfig: (
                guid: string,
            ) => Promise<ConfigResetAdvancedConfigResponse>;
            set: (key: string, value: JsonValue) => Promise<ConfigSetResponse>;
            setActiveDspPreset: (
                index: number,
            ) => Promise<ConfigSetActiveDspPresetResponse>;
            setAdvancedConfigValue: (
                guid: string,
                value: JsonValue,
            ) => Promise<ConfigSetAdvancedConfigValueResponse>;
            setCursorFollowPlayback: (
                enabled: boolean,
            ) => Promise<ConfigSetCursorFollowPlaybackResponse>;
            setOutputBuffer: {
                (ms: number): Promise<ConfigSetOutputBufferResponse>;
                (
                    opts: ConfigSetOutputBufferParams,
                ): Promise<ConfigSetOutputBufferResponse>;
            };
            setOutputDevice: (
                outputId: string,
                deviceId: string,
            ) => Promise<ConfigSetOutputDeviceResponse>;
            setPlaybackFollowCursor: (
                enabled: boolean,
            ) => Promise<ConfigSetPlaybackFollowCursorResponse>;
            setReplaygainMode: (
                mode: ReplaygainSourceMode | ReplaygainSourceModeName,
            ) => Promise<ConfigSetReplaygainModeResponse>;
            showLibraryPreferences: () => Promise<
                ConfigShowLibraryPreferencesResponse,
            >;
        };
        console: {
            error: (
                message: string,
                ...args: JsonValue[],
            ) => Promise<ConsoleErrorResponse>;
            log: (
                message: string,
                ...args: JsonValue[],
            ) => Promise<ConsoleLogResponse>;
            warn: (
                message: string,
                ...args: JsonValue[],
            ) => Promise<ConsoleWarnResponse>;
        };
        cursor: {
            isHidden: () => Promise<CursorIsHiddenResponse>;
            setHidden: (hidden: boolean) => Promise<CursorSetHiddenResponse>;
        };
        dialog: {
            confirm: (opts?: DialogConfirmParams) => Promise<DialogConfirmResponse>;
            openFile: (opts?: DialogOpenFileParams) => Promise<DialogOpenFileResponse>;
            openFolder: (
                opts?: DialogOpenFolderParams,
            ) => Promise<DialogOpenFolderResponse>;
            saveFile: (opts?: DialogSaveFileParams) => Promise<DialogSaveFileResponse>;
        };
        discovery: {
            executeContextMenuByPath: (
                opts: DiscoveryExecuteContextMenuByPathParams,
            ) => Promise<DiscoveryExecuteContextMenuByPathResponse>;
            executeContextMenuCommand: (
                opts: DiscoveryExecuteContextMenuCommandParams,
            ) => Promise<DiscoveryExecuteContextMenuCommandResponse>;
            executeMainMenuCommand: (
                guid: string,
                subGuid?: string,
            ) => Promise<DiscoveryExecuteMainMenuCommandResponse>;
            getAllServices: () => Promise<DiscoveryGetAllServicesResponse>;
            getComponents: () => Promise<DiscoveryGetComponentsResponse>;
            getContextMenuCommands: (
                opts?: DiscoveryGetContextMenuCommandsParams,
            ) => Promise<DiscoveryGetContextMenuCommandsResponse>;
            getContextMenuTree: () => Promise<DiscoveryGetContextMenuTreeResponse>;
            getDspEntries: () => Promise<DiscoveryGetDspEntriesResponse>;
            getInputFormats: () => Promise<DiscoveryGetInputFormatsResponse>;
            getMainMenuCommands: (
                opts?: DiscoveryGetMainMenuCommandsParams,
            ) => Promise<DiscoveryGetMainMenuCommandsResponse>;
            getMainMenuGroups: () => Promise<DiscoveryGetMainMenuGroupsResponse>;
            getOutputDevices: () => Promise<DiscoveryGetOutputDevicesResponse>;
            getPreferencePages: () => Promise<DiscoveryGetPreferencePagesResponse>;
            getUIElements: () => Promise<DiscoveryGetUIElementsResponse>;
            searchCommands: (
                query: string,
                opts?: Omit<DiscoverySearchCommandsParams, "query">,
            ) => Promise<DiscoverySearchCommandsResponse>;
        };
        dnd: {
            applyDragToken: (dataTransfer: DataTransfer, token: string) => void;
            getCapabilities: () => Promise<DndGetCapabilitiesResponse>;
            getPaths: () => string[];
            getPathsAsync: (sessionId?: string) => Promise<DndGetPathsAsyncResponse>;
            getResolvedPaths: () => (string | null)[];
            hasFiles: () => boolean;
            onDragEnded: (
                handler: (payload: DndDragEndedPayload) => void,
            ) => () => void;
            prepareDrag: (paths: string[]) => Promise<DndPrepareDragResponse>;
            startDrag: (_type?: string) => Promise<DndStartDragResponse>;
        };
        dsp: {
            addDsp: (guid: string, position?: number) => Promise<DspAddDspResponse>;
            applyPreset: (
                indexOrName: string | number,
            ) => Promise<DspApplyPresetResponse>;
            getAvailable: () => Promise<DspGetAvailableResponse>;
            getChain: () => Promise<DspGetChainResponse>;
            getPresets: () => Promise<DspGetPresetsResponse>;
            moveDsp: (from: number, to: number) => Promise<DspMoveDspResponse>;
            removeDsp: (index: number) => Promise<DspRemoveDspResponse>;
            setChain: (
                dsps: readonly Pick<DspChainSpec, "guid">[],
            ) => Promise<DspSetChainResponse>;
        };
        event: {
            emit: (
                eventName: string,
                payload?: JsonValue,
                excludeSelf?: boolean,
            ) => Promise<EventEmitResponse>;
            emitTo: (
                eventName: string,
                payload: JsonValue,
                targetWindowId: string,
            ) => Promise<EventEmitToResponse>;
        };
        file: {
            cancelOp: (operationId: string) => Promise<FileCancelOpResponse>;
            copy: (
                source: string,
                destination: string,
                opts?: Omit<FileCopyParams, "source" | "destination">,
            ) => Promise<FileCopyResponse>;
            copyAsync: (
                items: FileOpEntry[],
                opts?: FileOpAsyncOptions,
            ) => Promise<FileCopyAsyncResponse>;
            delete: (
                path: string,
                opts?: Omit<FileDeleteParams, "path">,
            ) => Promise<FileDeleteResponse>;
            deleteAsync: (
                paths: string[],
                opts?: FileDeleteAsyncOptions,
            ) => Promise<FileDeleteAsyncResponse>;
            exists: (path: string) => Promise<FileExistsResponse>;
            getInfo: (path: string) => Promise<FileGetInfoResponse>;
            list: (
                path: string,
                opts?: Omit<FileListParams, "path">,
            ) => Promise<FileListResponse>;
            mkdir: (path: string) => Promise<FileMkdirResponse>;
            move: (source: string, destination: string) => Promise<FileMoveResponse>;
            moveAsync: (
                items: FileOpEntry[],
                opts?: FileOpAsyncOptions,
            ) => Promise<FileMoveAsyncResponse>;
            read: (
                path: string,
                opts?: Omit<FileReadParams, "path">,
            ) => Promise<FileReadResponse>;
            readBinary: (path: string) => Promise<Uint8Array<ArrayBufferLike>>;
            rename: (path: string, newName: string) => Promise<FileRenameResponse>;
            write: (
                path: string,
                content: string,
                opts?: Omit<FileWriteParams, "content" | "path">,
            ) => Promise<FileWriteResponse>;
            writeBinary: (
                path: string,
                bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
                opts?: FileBinaryWriteOptions,
            ) => Promise<FileWriteResponse>;
            writeDataUrl: (
                path: string,
                dataUrl: string,
                opts?: FileBinaryWriteOptions,
            ) => Promise<FileWriteResponse>;
        };
        http: {
            abort: (requestId: string) => Promise<HttpAbortResponse>;
            delete: {
                (url: string, body?: JsonValue): Promise<HttpGetResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpBinaryRequestOptions,
                ): Promise<HttpBinaryResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpRequestOptions,
                ): Promise<HttpGetResponse>;
            };
            disableDefaultDownloadLogger: () => void;
            download: (
                url: string,
                saveTo: string,
                opts?: HttpDownloadOptions,
            ) => Promise<HttpDownloadResponse>;
            get: {
                (url: string): Promise<HttpGetResponse>;
                (
                    url: string,
                    opts: HttpBinaryRequestOptions,
                ): Promise<HttpBinaryResponse>;
                (url: string, opts: HttpRequestOptions): Promise<HttpGetResponse>;
            };
            head: (
                url: string,
                opts?: Omit<HttpRequestOptions, "responseType">,
            ) => Promise<HttpHeadResponse>;
            patch: {
                (url: string, body?: JsonValue): Promise<HttpGetResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpBinaryRequestOptions,
                ): Promise<HttpBinaryResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpRequestOptions,
                ): Promise<HttpGetResponse>;
            };
            post: {
                (url: string, body?: JsonValue): Promise<HttpGetResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpBinaryRequestOptions,
                ): Promise<HttpBinaryResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpRequestOptions,
                ): Promise<HttpGetResponse>;
            };
            put: {
                (url: string, body?: JsonValue): Promise<HttpGetResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpBinaryRequestOptions,
                ): Promise<HttpBinaryResponse>;
                (
                    url: string,
                    body: JsonValue,
                    opts: HttpRequestOptions,
                ): Promise<HttpGetResponse>;
            };
            request: {
                (url: string): Promise<HttpGetSuccess>;
                (url: string, opts: HttpBinaryRequestOptions): Promise<HttpBinarySuccess>;
                (url: string, opts: HttpRequestOptions): Promise<HttpGetSuccess>;
            };
        };
        invoke: <TResp = unknown>(
            method: string,
            params?: object,
        ) => Promise<TResp>;
        isAvailable: () => boolean;
        jitQueue: {
            clear: () => Promise<JitQueueClearResponse>;
            enqueueNext: (
                opts: JitQueueEnqueueNextParams,
            ) => Promise<JitQueueEnqueueNextResponse>;
            getState: () => Promise<JitQueueGetStateResponse>;
            notifyEmpty: () => Promise<JitQueueNotifyEmptyResponse>;
            playNow: (opts: JitQueuePlayNowParams) => Promise<JitQueuePlayNowResponse>;
            preloadBatch: (
                opts: JitQueuePreloadBatchParams,
            ) => Promise<JitQueuePreloadBatchResponse>;
            skip: () => Promise<JitQueueSkipResponse>;
            stop: (opts?: JitQueueStopParams) => Promise<JitQueueStopResponse>;
        };
        jitSession: {
            adoptNative: (
                params: JitSessionAdoptNativeParams,
            ) => Promise<JitSessionAdoptNativeResponse>;
            claimControl: (
                params: JitSessionClaimControlParams,
            ) => Promise<JitSessionClaimControlResponse>;
            create: (
                params: JitSessionCreateParams,
            ) => Promise<JitSessionCreateResponse>;
            discover: () => Promise<JitSessionDiscoverResponse>;
            getCapabilities: () => Promise<JitSessionGetCapabilitiesResponse>;
            getNativeContext: (
                params: JitSessionGetNativeContextParams,
            ) => Promise<JitSessionGetNativeContextResponse>;
            getOperation: (
                params: JitSessionGetOperationParams,
            ) => Promise<JitSessionGetOperationResponse>;
            getState: (
                params: JitSessionGetStateParams,
            ) => Promise<JitSessionGetStateResponse>;
            play: (params: JitSessionPlayParams) => Promise<JitSessionPlayResponse>;
            playNative: (
                params: JitSessionPlayNativeParams,
            ) => Promise<JitSessionPlayNativeResponse>;
            prepareAdoption: (
                params: JitSessionPrepareAdoptionParams,
            ) => Promise<JitSessionPrepareAdoptionResponse>;
            release: (
                params: JitSessionReleaseParams,
            ) => Promise<JitSessionReleaseResponse>;
            setNativeNext: (
                params: JitSessionSetNativeNextParams,
            ) => Promise<JitSessionSetNativeNextResponse>;
            setNativeQueue: (
                params: JitSessionSetNativeQueueParams,
            ) => Promise<JitSessionSetNativeQueueResponse>;
            setNext: (
                params: JitSessionSetNextParams,
            ) => Promise<JitSessionSetNextResponse>;
            skip: (params: JitSessionSkipParams) => Promise<JitSessionSkipResponse>;
            stop: (params: JitSessionStopParams) => Promise<JitSessionStopResponse>;
        };
        JitSessionClient: typeof JitSessionClient;
        keyboard: {
            getRegisteredHotkeys: () => Promise<
                KeyboardGetRegisteredHotkeysResponse,
            >;
            registerHotkey: (
                key: string,
                action: string,
                opts?: Omit<KeyboardRegisterHotkeyParams, "key" | "action">,
            ) => Promise<KeyboardRegisterHotkeyResponse>;
            registerShortcut: (
                key: string,
                action: string,
            ) => Promise<KeyboardRegisterShortcutResponse>;
            setReservedKeys: (
                keys: string[],
                options?: { all?: boolean },
            ) => Promise<KeyboardSetReservedKeysResponse>;
            unregisterHotkey: (
                opts: KeyboardUnregisterHotkeyParams,
            ) => Promise<KeyboardUnregisterHotkeyResponse>;
        };
        library: {
            addToPlaylist: (
                paths: string[],
                playlist?: PlaylistRef,
            ) => Promise<LibraryAddToPlaylistResponse>;
            browseDirectory: (
                path: string,
                includeFiles?: boolean,
            ) => Promise<LibraryBrowseDirectoryResponse>;
            browseTree: (
                params: LibraryBrowseTreeParams,
            ) => Promise<LibraryBrowseTreeResponse>;
            enumerateDirectories: (
                options?: LibraryEnumerateDirectoriesOptions,
            ) => AsyncGenerator<
                LibraryDirectoryBatch,
                LibraryEnumerateDirectoriesSummary,
                void,
            >;
            enumerateFieldValues: (
                field: string,
                options?: LibraryEnumerateFieldValuesOptions,
            ) => Promise<LibraryGetFieldValuesResponse>;
            enumerateTracks: (
                options?: LibraryEnumerateTracksOptions,
            ) => AsyncGenerator<
                LibraryEnumerateTracksPage,
                LibraryEnumerateTracksSummary,
                void,
            >;
            enumerateTree: (
                options: LibraryEnumerateTreeOptions,
            ) => AsyncGenerator<LibraryTreeBatch, LibraryEnumerateTreeSummary, void>;
            getAlbums: (
                options?: number | LibraryGetAlbumsParams,
            ) => Promise<LibraryGetAlbumsResponse>;
            getAlbumTracks: (
                album: string,
                albumArtist: string,
                options?: Pick<LibraryGetAlbumTracksParams, "albumId">,
            ) => Promise<LibraryGetAlbumTracksResponse>;
            getAll: (
                start?: number,
                count?: number,
                opts?: Pick<LibraryGetAllParams, "useCache" | "asyncResult"> & {
                    timeout?: number;
                },
            ) => Promise<ApiFailure | LibraryPagedTracksResponse>;
            getArtistAlbums: (
                artist: string,
                limit?: number,
                options?: Omit<LibraryGetArtistAlbumsParams, "artist" | "limit">,
            ) => Promise<LibraryGetArtistAlbumsResponse>;
            getArtists: (
                limit?: number,
                options?: Omit<LibraryGetArtistsParams, "limit">,
            ) => Promise<LibraryGetArtistsResponse>;
            getArtistTracks: (
                artist: string,
                limit?: number,
            ) => Promise<LibraryGetArtistTracksResponse>;
            getByPath: (path: string) => Promise<LibraryGetByPathResponse>;
            getCacheStats: () => Promise<LibraryGetCacheStatsResponse>;
            getChanges: (
                params?: LibraryGetChangesParams,
            ) => Promise<LibraryGetChangesResponse>;
            getCount: () => Promise<LibraryGetCountResponse>;
            getFieldValues: (
                field: string,
                limit?: number,
                separator?: string,
            ) => Promise<LibraryGetFieldValuesResponse>;
            getGenres: () => Promise<LibraryGetGenresResponse>;
            getRandomTracks: (
                count?: number,
            ) => Promise<LibraryGetRandomTracksResponse>;
            getRecentlyAdded: (
                limit?: number,
                sortBy?: "added" | "modified",
            ) => Promise<LibraryGetRecentlyAddedResponse>;
            getRoots: () => Promise<LibraryGetRootsResponse>;
            getStats: () => Promise<LibraryGetStatsResponse>;
            getStatus: () => Promise<LibraryGetStatusResponse>;
            getTracks: (
                handles: string[],
                fields?: string[],
            ) => Promise<LibraryGetTracksResponse>;
            invalidateCache: () => Promise<LibraryInvalidateCacheResponse>;
            isEnabled: () => Promise<LibraryIsEnabledResponse>;
            query: (
                query: string,
                sort?: string,
                limit?: number,
                fields?: string[],
            ) => Promise<LibraryQueryResponse>;
            refresh: () => Promise<LibraryRefreshResponse>;
            rescan: () => Promise<LibraryRescanResponse>;
            search: (
                query: string,
                limit?: number,
                options?: Omit<LibrarySearchParams, "limit" | "query">,
            ) => Promise<LibrarySearchResponse>;
        };
        log: {
            clear: () => Promise<LogClearResponse>;
            read: (lines?: number) => Promise<LogReadResponse>;
            write: (
                message: string,
                opts?: LogWriteParams,
            ) => Promise<LogWriteResponse>;
        };
        lyrics: {
            exists: (
                path: string,
                options?: Omit<LyricsExistsParams, "path">,
            ) => Promise<LyricsExistsResponse>;
            get: (
                path?: string,
                options?: Omit<LyricsGetParams, "path">,
            ) => Promise<LyricsGetResponse>;
            save: (
                path: string,
                lyricsText: string,
                opts?: LyricsSaveOptions,
            ) => Promise<LyricsSaveResponse>;
        };
        media: {
            canPlay: (
                track: ContainerTrack,
                limits?: MediaVideoDecodingLimits,
            ) => Promise<MediaCanPlayResult>;
            getContainerInfo: (path: string) => Promise<MediaGetContainerInfoResponse>;
            getStreamUrl: (path: string) => Promise<MediaGetStreamUrlResponse>;
        };
        MediaElementFollower: typeof MediaElementFollower;
        menu: {
            close: (reason?: string) => Promise<MenuCloseResponse>;
            getContextMenu: (
                opts?: MenuGetContextMenuParams,
            ) => Promise<MenuGetContextMenuResponse>;
            getMainMenu: (
                root?: string,
                opts?: Omit<MenuGetMainMenuParams, "root">,
            ) => Promise<MenuGetMainMenuResponse>;
            popup: (
                items: MenuPopupItem[],
                position?: MenuPopupPosition,
                opts?: MenuPopupOptions,
            ) => Promise<string | null>;
            runContextCommand: (
                command: string,
                opts?: Omit<MenuRunContextCommandParams, "command">,
            ) => Promise<MenuRunContextCommandResponse>;
            runContextCommandById: (
                id: number,
                opts?: Omit<MenuRunContextCommandByIdParams, "id">,
            ) => Promise<MenuRunContextCommandByIdResponse>;
            runMainMenuCommand: (
                command: string,
                opts?: Omit<MenuRunMainMenuCommandParams, "command">,
            ) => Promise<MenuRunMainMenuCommandResponse>;
            show: (
                items: MenuPopupItem[],
                position?: MenuPopupPosition,
                opts?: MenuPopupOptions,
            ) => Promise<MenuShowResponse>;
            showNativePopup: (
                opts?: MenuShowNativePopupParams,
            ) => Promise<MenuShowNativePopupResponse>;
        };
        metadata: {
            cancelProbe: (
                operationId: string,
            ) => Promise<MetadataCancelProbeResponse>;
            disableDefaultLogger: () => void;
            embedArtwork: (
                path: string,
                opts: Omit<MetadataEmbedArtworkParams, "path" | "target"> & {
                    target?: string | string[];
                },
            ) => Promise<MetadataEmbedArtworkResponse>;
            embedArtworkBytes: (
                path: string,
                bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
                opts?: MetadataArtworkBytesOptions,
            ) => Promise<MetadataEmbedArtworkResponse>;
            embedArtworkFromDataUrl: (
                path: string,
                dataUrl: string,
                opts?: MetadataArtworkBytesOptions,
            ) => Promise<MetadataEmbedArtworkResponse>;
            probeBatchAsync: (
                paths: string[],
                opts?: Omit<MetadataProbeBatchAsyncParams, "paths">,
            ) => Promise<MetadataProbeBatchAsyncResponse>;
            read: (
                path: string,
                opts?: Omit<MetadataReadParams, "path">,
            ) => Promise<MetadataReadResponse>;
            readBatch: (paths: string[]) => Promise<MetadataReadBatchResponse>;
            readByPath: (
                path: string,
                opts?: Omit<MetadataReadByPathParams, "path">,
            ) => Promise<MetadataReadByPathResponse>;
            readRaw: (
                path: string,
                opts?: Omit<MetadataReadRawParams, "path">,
            ) => Promise<MetadataReadRawResponse>;
            removeEmbeddedArt: (
                path: string,
                opts?: Omit<MetadataRemoveEmbeddedArtParams, "path">,
            ) => Promise<MetadataRemoveEmbeddedArtResponse>;
            removeField: (
                path: string,
                field: string,
                opts?: Omit<MetadataRemoveFieldParams, "path" | "tags">,
            ) => Promise<MetadataRemoveFieldResponse>;
            removeTag: (
                path: string,
                tags: string[],
                opts?: Omit<MetadataRemoveTagParams, "path" | "tags">,
            ) => Promise<MetadataRemoveTagResponse>;
            write: (
                path: string,
                tags: JsonObject,
                opts?: Omit<MetadataWriteParams, "path" | "tags">,
            ) => Promise<MetadataWriteResponse>;
            writeBatch: (
                items: MetadataWriteBatchItem[],
            ) => Promise<MetadataWriteBatchResponse>;
        };
        misc: {
            exit: () => Promise<MiscExitResponse>;
            getComponentPath: () => Promise<MiscGetComponentPathResponse>;
            getFoobarPath: () => Promise<MiscGetFoobarPathResponse>;
            getProfilePath: () => Promise<MiscGetProfilePathResponse>;
            restart: () => Promise<MiscRestartResponse>;
            showConsole: () => Promise<MiscShowConsoleResponse>;
            showLibrarySearch: (
                query?: string,
            ) => Promise<MiscShowLibrarySearchResponse>;
            showPopupMessage: (
                message: string,
                title?: string,
            ) => Promise<MiscShowPopupMessageResponse>;
            showPreferences: () => Promise<MiscShowPreferencesResponse>;
        };
        notification: {
            hide: () => Promise<UiHideNotificationResponse>;
            show: (
                opts: UiShowNotificationParams,
            ) => Promise<UiShowNotificationResponse>;
            showCustomMenu: (
                opts: UiShowCustomMenuParams,
            ) => Promise<UiShowCustomMenuResponse>;
            showToast: (opts: UiShowToastParams) => Promise<UiShowToastResponse>;
        };
        off: (event: string, handler: RawEventHandler) => void;
        on: {
            <K extends FBEventName>(
                event: K,
                handler: FBEventHandler<K>,
            ): () => void;
            (event: string, handler: RawEventHandler): () => void;
        };
        once: {
            <K extends FBEventName>(
                event: K,
                handler: FBEventHandler<K>,
            ): () => void;
            (event: string, handler: RawEventHandler): () => void;
        };
        output: {
            getDevices: () => Promise<OutputGetDevicesResponse>;
            getEntries: () => Promise<OutputGetEntriesResponse>;
            getSettings: () => Promise<OutputGetSettingsResponse>;
        };
        panel: {
            getConfig: () => Promise<PanelGetConfigResponse>;
            setConfig: (opts: PanelSetConfigParams) => Promise<PanelSetConfigResponse>;
        };
        PlaybackClock: typeof PlaybackClock;
        playcount: {
            get: (path: string) => Promise<PlaycountGetResponse>;
            getBatch: (paths: string[]) => Promise<PlaycountGetBatchResponse>;
            getStats: () => Promise<PlaycountGetStatsResponse>;
            set: (path: string, count: number) => Promise<PlaycountSetResponse>;
        };
        player: {
            getCurrentTrack: () => Promise<PlaybackGetCurrentTrackResponse>;
            getCurrentTrackIndex: (
                includeTrackInfo?: boolean,
            ) => Promise<PlaybackGetCurrentTrackIndexResponse>;
            getOrder: () => Promise<PlaybackGetPlaybackOrderResponse>;
            getPlayingPlaylist: () => Promise<PlaybackGetPlayingPlaylistResponse>;
            getPosition: () => Promise<PlaybackGetPositionResponse>;
            getState: () => Promise<PlaybackGetStateResponse>;
            getStopAfterCurrent: () => Promise<PlaybackGetStopAfterCurrentResponse>;
            getVolume: () => Promise<PlaybackGetVolumeResponse>;
            mute: (muted?: boolean) => Promise<PlaybackMuteResponse>;
            next: () => Promise<PlaybackNextResponse>;
            pause: () => Promise<PlaybackPauseResponse>;
            play: () => Promise<PlaybackPlayResponse>;
            playPath: (path: string) => Promise<PlaybackPlayPathResponse>;
            playPaths: {
                (
                    paths: string[],
                    startIndex?: number,
                ): Promise<PlaybackPlayPathsResponse>;
                (
                    paths: string[],
                    opts: { replace?: boolean; startIndex?: number },
                ): Promise<PlaybackPlayPathsResponse>;
            };
            playPause: () => Promise<PlaybackPlayPauseResponse>;
            prev: () => Promise<PlaybackPreviousResponse>;
            random: () => Promise<PlaybackRandomResponse>;
            seek: (seconds: number) => Promise<PlaybackSetPositionResponse>;
            setOrder: (
                order: number | PlaybackOrder,
            ) => Promise<PlaybackSetPlaybackOrderResponse>;
            setStopAfterCurrent: (
                enabled: boolean,
            ) => Promise<PlaybackSetStopAfterCurrentResponse>;
            setVolume: (volume: number) => Promise<PlaybackSetVolumeResponse>;
            stop: () => Promise<PlaybackStopResponse>;
            toggle: () => Promise<PlaybackPlayOrPauseResponse>;
            toggleMute: () => Promise<PlaybackToggleMuteResponse>;
            toggleStopAfterCurrent: () => Promise<
                PlaybackToggleStopAfterCurrentResponse,
            >;
            volumeDown: () => Promise<PlaybackVolumeDownResponse>;
            volumeUp: () => Promise<PlaybackVolumeUpResponse>;
        };
        playlist: {
            add: (
                playlist: PlaylistRef,
                paths: string[],
            ) => Promise<PlaylistAddPathsResponse>;
            addAsync: (
                playlist: PlaylistRef,
                paths: string[],
            ) => Promise<PlaylistAddPathsAsyncResponse>;
            addHandles: (
                playlist: PlaylistRef,
                handles: PlaylistHandleRef[],
            ) => Promise<PlaylistAddHandlesResponse>;
            addSequential: (
                playlist: PlaylistRef,
                paths: string[],
            ) => Promise<PlaylistAddPathsSequentialResponse>;
            clear: (playlist: PlaylistRef) => Promise<PlaylistClearResponse>;
            convertToAutoplaylist: (
                playlist: PlaylistRef,
                query: string,
                sort?: string,
                keepSorted?: boolean,
            ) => Promise<PlaylistConvertToAutoplaylistResponse>;
            create: (
                name: string,
                options?: Omit<PlaylistCreateParams, "name">,
            ) => Promise<PlaylistCreateResponse>;
            createAutoplaylist: (
                name: string,
                query: string,
                sort?: string,
                keepSorted?: boolean,
            ) => Promise<PlaylistCreateAutoplaylistResponse>;
            createManagedAutoplaylist: (
                name: string,
                query: string,
                sort?: string,
                keepSorted?: boolean,
            ) => Promise<PlaylistCreateManagedAutoplaylistResponse>;
            deselectAll: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistDeselectAllResponse>;
            duplicate: (
                playlist: PlaylistRef,
                name?: string,
            ) => Promise<PlaylistDuplicateResponse>;
            focusTrack: (
                playlist: PlaylistRef,
                trackIndex: number,
            ) => Promise<PlaylistFocusTrackResponse>;
            getActive: () => Promise<PlaylistGetActiveResponse>;
            getAll: () => Promise<PlaylistGetAllResponse>;
            getAutoplaylistConfig: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetAutoplaylistConfigResponse>;
            getAutoplaylistInfo: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetAutoplaylistInfoResponse>;
            getAutoplaylistQuery: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetAutoplaylistQueryResponse>;
            getAvailableColumns: () => Promise<PlaylistGetAvailableColumnsResponse>;
            getCount: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetTrackCountResponse>;
            getFocused: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetFocusedTrackResponse>;
            getFocusTrack: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetFocusTrackResponse>;
            getGroupRuns: (
                patterns: string[],
                playlist?: PlaylistRef,
            ) => Promise<PlaylistGetGroupRunsResponse>;
            getLockInfo: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetLockInfoResponse>;
            getMatchingRows: (
                query: string,
                playlist?: PlaylistRef,
            ) => Promise<PlaylistGetMatchingRowsResponse>;
            getPlaying: () => Promise<PlaylistGetPlayingResponse>;
            getPlaylistCount: () => Promise<PlaylistGetCountResponse>;
            getSelectedTracks: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetSelectedTracksResponse>;
            getSelection: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistGetSelectionResponse>;
            getTracks: (
                playlist: PlaylistRef,
                start?: number,
                count?: number,
                formats?: Record<string, string>,
                fields?: string[],
            ) => Promise<PlaylistGetTracksResponse>;
            getTracksAt: (
                playlist: PlaylistRef,
                rows: readonly number[],
                formats?: Record<string, string>,
                fields?: string[],
            ) => Promise<PlaylistGetTracksAtResponse>;
            getTracksPage: (
                playlist: PlaylistRef,
                start?: number,
                count?: number,
                formats?: Record<string, string>,
                fields?: string[],
            ) => Promise<PlaylistGetTracksResponse>;
            insertTracks: (
                playlist: PlaylistRef,
                insertIndex: number,
                handles: PlaylistHandleRef[],
                expectedVersion?: string,
            ) => Promise<PlaylistInsertTracksResponse>;
            isAutoplaylist: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistIsAutoplaylistResponse>;
            isLocked: (playlist: PlaylistRef) => Promise<PlaylistIsLockedResponse>;
            moveTracks: (
                playlist: PlaylistRef,
                indices: number[],
                delta: number,
                expectedVersion?: string,
            ) => Promise<PlaylistMoveTracksResponse>;
            onAutoplaylistConfigChanged: (
                callback: (event: PlaylistAutoplaylistConfigChangedPayload) => void,
            ) => () => void;
            onAutoplaylistUIResult: (
                callback: (event: PlaylistAutoplaylistUIResultPayload) => void,
            ) => () => void;
            playTrack: (
                playlist: PlaylistRef,
                trackIndex: number,
                options?: Omit<
                    PlaylistPlayTrackParams,
                    "index"
                    | "playlist"
                    | "playlistGuid",
                >,
            ) => Promise<PlaylistPlayTrackResponse>;
            redo: (playlist: PlaylistRef) => Promise<PlaylistRedoResponse>;
            remove: (playlist: PlaylistRef) => Promise<PlaylistRemoveResponse>;
            removeAutoplaylist: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistRemoveAutoplaylistResponse>;
            removeSelectedTracks: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistRemoveSelectedTracksResponse>;
            removeTracks: (
                playlist: PlaylistRef,
                indices: number[],
                expectedVersion?: string,
            ) => Promise<PlaylistRemoveTracksResponse>;
            rename: (
                playlist: PlaylistRef,
                name: string,
            ) => Promise<PlaylistRenameResponse>;
            reorder: (
                playlist: PlaylistRef,
                order: number[],
                expectedVersion?: string,
            ) => Promise<PlaylistReorderResponse>;
            reorderPlaylists: (
                order: readonly string[] | readonly number[],
            ) => Promise<PlaylistReorderPlaylistsResponse>;
            replaceAllAndPlay: (
                options: PlaylistReplaceAllAndPlayParams,
            ) => Promise<PlaylistReplaceAllAndPlayResponse>;
            reverse: (playlist: PlaylistRef) => Promise<PlaylistReverseResponse>;
            selectAll: (playlist: PlaylistRef) => Promise<PlaylistSelectAllResponse>;
            setActive: (playlist: PlaylistRef) => Promise<PlaylistSetActiveResponse>;
            setAutoplaylistConfig: (
                playlist: PlaylistRef,
                options: Omit<
                    PlaylistSetAutoplaylistConfigParams,
                    "playlist"
                    | "playlistGuid",
                >,
            ) => Promise<PlaylistSetAutoplaylistConfigResponse>;
            setFocused: (
                playlist: PlaylistRef,
                trackIndex: number,
                expectedVersion?: string,
            ) => Promise<PlaylistSetFocusedTrackResponse>;
            setSelection: (
                playlist: PlaylistRef,
                indices: number[],
                clearOthers?: boolean,
                expectedVersion?: string,
            ) => Promise<PlaylistSetSelectionResponse>;
            showAutoplaylistUI: (
                playlist: PlaylistRef,
            ) => Promise<PlaylistShowAutoplaylistUIResponse>;
            shuffle: (playlist: PlaylistRef) => Promise<PlaylistShuffleResponse>;
            sort: (
                playlist: PlaylistRef,
                pattern: string,
                descending?: boolean,
                selectedOnly?: boolean,
            ) => Promise<PlaylistSortResponse>;
            undo: (playlist: PlaylistRef) => Promise<PlaylistUndoResponse>;
        };
        port: {
            connect: (name: string) => Promise<PortConnectResponse>;
            disconnect: (portId: string) => Promise<PortDisconnectResponse>;
            getPorts: (name?: string) => Promise<PortGetPortsResponse>;
            onConnect: (handler: (data: unknown) => void) => () => void;
            onDisconnect: (handler: (data: unknown) => void) => () => void;
            onMessage: (handler: (data: unknown) => void) => () => void;
            postMessage: (
                portId: string,
                message: JsonValue,
            ) => Promise<PortPostMessageResponse>;
            postMessageTo: (
                portId: string,
                targetPortId: string,
                message: JsonValue,
            ) => Promise<PortPostMessageToResponse>;
        };
        queue: {
            add: (opts: QueueAddParams) => Promise<QueueAddResponse>;
            addPaths: (
                paths: string[],
                opts?: Omit<QueueAddPathsParams, "paths">,
            ) => Promise<QueueAddPathsResponse>;
            clear: () => Promise<QueueClearResponse>;
            flush: () => Promise<QueueFlushResponse>;
            get: () => Promise<QueueGetResponse>;
            getCount: () => Promise<QueueGetCountResponse>;
            insertNext: (
                entries: (string | QueueListRef)[],
                position?: number,
                expectedVersion?: string,
            ) => Promise<QueueInsertNextResponse>;
            moveToTop: (
                index: number,
                expectedVersion?: string,
            ) => Promise<QueueMoveToTopResponse>;
            playNow: (
                index?: number,
                expectedVersion?: string,
            ) => Promise<QueuePlayNowResponse>;
            remove: (
                target: number | number[],
                expectedVersion?: string,
            ) => Promise<QueueRemoveResponse>;
            setContents: (
                items: QueueContentRef[],
                expectedVersion?: string,
            ) => Promise<QueueSetContentsResponse>;
        };
        rating: {
            get: (
                path: string,
                opts?: { cueIndex?: number },
            ) => Promise<RatingGetResponse>;
            set: (
                path: string,
                rating: number,
                opts?: { cueIndex?: number },
            ) => Promise<RatingSetResponse>;
        };
        ready: () => Promise<void>;
        replaygain: {
            clear: (paths: string[]) => Promise<ReplaygainClearResponse>;
            get: (paths: string | string[]) => Promise<ReplaygainGetResponse>;
            getMode: () => Promise<ReplaygainGetModeResponse>;
            getPreamp: () => Promise<ReplaygainGetPreampResponse>;
            getSettings: () => Promise<ReplaygainGetSettingsResponse>;
            scan: (
                paths: string[],
                opts?: { mode?: "track" | "album" },
            ) => Promise<ReplaygainScanResponse>;
            setMode: (
                sourceMode: NonNullable<
                    "auto"
                    | "none"
                    | "track"
                    | "album"
                    | "byPlaybackOrder"
                    | undefined,
                >,
                processingMode?: "gain" | "none" | "peak" | "gain_and_peak",
            ) => Promise<ReplaygainSetModeResponse>;
            setPreamp: (
                withRg?: number,
                withoutRg?: number,
            ) => Promise<ReplaygainSetPreampResponse>;
        };
        selection: {
            get: (opts?: SelectionGetParams) => Promise<SelectionGetResponse>;
            getType: () => Promise<SelectionGetTypeResponse>;
            getViewerMode: () => Promise<SelectionGetViewerModeResponse>;
            getViewingTrack: (
                opts?: SelectionGetViewingTrackParams,
            ) => Promise<SelectionGetViewingTrackResponse>;
            set: (handles: string[]) => Promise<SelectionSetResponse>;
            setPlaylistTracking: (
                mode?: NonNullable<"playlist" | "selection" | undefined>,
            ) => Promise<SelectionSetPlaylistTrackingResponse>;
        };
        sharedState: {
            delete: (key: string) => Promise<StateDeleteResponse>;
            get: (key: string) => Promise<StateGetResponse>;
            keys: (pattern?: string) => Promise<StateKeysResponse>;
            onChange: (handler: (data: unknown) => void) => () => void;
            onDelete: (handler: (data: unknown) => void) => () => void;
            set: (
                key: string,
                value: JsonValue,
                silent?: boolean,
                ttlMs?: number,
            ) => Promise<StateSetResponse>;
        };
        shell: {
            exec: (
                command: string,
                options?: Omit<ShellExecParams, "command">,
            ) => Promise<ShellExecResponse>;
            openExternal: (url: string) => Promise<ShellOpenExternalResponse>;
            openWith: (path: string) => Promise<ShellOpenWithResponse>;
            showInExplorer: (path: string) => Promise<ShellShowInExplorerResponse>;
            spawn: (
                executable: string,
                options?: Omit<ShellSpawnParams, "executable">,
            ) => Promise<ShellSpawnResponse>;
        };
        state: ReactiveState;
        system: {
            getApisByNamespace: (
                namespace: string,
            ) => Promise<SystemGetApisByNamespaceResponse>;
            getApiStats: () => Promise<SystemGetApiStatsResponse>;
            getDPI: () => Promise<SystemGetDPIResponse>;
            getLocale: () => Promise<SystemGetLocaleResponse>;
            getRegisteredPlugins: () => Promise<SystemGetRegisteredPluginsResponse>;
            getTheme: () => Promise<SystemGetThemeResponse>;
            isPluginRegistered: (
                namespace: string,
            ) => Promise<SystemIsPluginRegisteredResponse>;
            listApis: (
                includeInternal?: boolean,
                includeExternal?: boolean,
            ) => Promise<SystemListAvailableApisResponse>;
            searchApis: (query: string) => Promise<SystemSearchApisResponse>;
        };
        taskbar: {
            flash: (opts?: TaskbarFlashParams) => Promise<TaskbarFlashResponse>;
            setOverlayIcon: (
                opts?: TaskbarSetOverlayIconParams,
            ) => Promise<TaskbarSetOverlayIconResponse>;
            setProgress: (
                opts: TaskbarSetProgressParams,
            ) => Promise<TaskbarSetProgressResponse>;
            setThumbnailButtons: (
                buttons: ThumbnailButton[],
            ) => Promise<TaskbarSetThumbnailButtonsResponse>;
            updateButton: (
                opts: TaskbarUpdateButtonParams,
            ) => Promise<TaskbarUpdateButtonResponse>;
        };
        titleformat: {
            eval: (
                pattern: string,
                path?: string,
            ) => Promise<TitleformatEvalResponse>;
            evalBatch: (
                pattern: string,
                paths: string[],
            ) => Promise<TitleformatEvalBatchResponse>;
            evalFields: (
                path: string,
                fields: TitleformatFieldMap,
            ) => Promise<TitleformatEvalFieldsResponse>;
            evalFieldsBatch: (
                paths: string[],
                fields: TitleformatFieldMap,
            ) => Promise<TitleformatEvalFieldsBatchResponse>;
            getBuiltinFields: () => Promise<TitleformatGetBuiltinFieldsResponse>;
        };
        tray: {
            appendMenuItems: (
                items: TrayMenuItem[],
                position?: TrayMenuPosition,
            ) => Promise<TrayAppendMenuItemsResponse>;
            clearMenuItems: (
                position?: TrayMenuPosition,
            ) => Promise<TrayClearMenuItemsResponse>;
            create: (
                opts?: { icon?: string | null; tooltip?: string },
            ) => Promise<TrayCreateResponse>;
            destroy: () => Promise<TrayDestroyResponse>;
            getMenuItems: () => Promise<TrayGetMenuItemsResponse>;
            isVisible: () => Promise<TrayIsVisibleResponse>;
            removeMenuItems: (ids: string[]) => Promise<TrayRemoveMenuItemsResponse>;
            setClickAction: (
                action: "event" | "toggleMainWindow",
            ) => Promise<TraySetClickActionResponse>;
            setCloseToTray: (enabled: boolean) => Promise<TraySetCloseToTrayResponse>;
            setContextMenu: (
                items: TrayMenuItem[],
                config?: TrayMenuConfig,
            ) => Promise<TraySetContextMenuResponse>;
            setIcon: (icon?: string | null) => Promise<TraySetIconResponse>;
            setMenuItemState: (
                id: string,
                state: { checked?: boolean; enabled?: boolean },
            ) => Promise<TraySetMenuItemStateResponse>;
            setMenuZones: (
                zones: Omit<TraySetMenuZonesParams, "config">,
                config?: TrayMenuConfig,
            ) => Promise<TraySetMenuZonesResponse>;
            setMinimizeToTray: (
                enabled: boolean,
            ) => Promise<TraySetMinimizeToTrayResponse>;
            setTooltip: (tooltip: string) => Promise<TraySetTooltipResponse>;
            showBalloon: (
                opts: {
                    icon?: "error" | "info" | "warning";
                    message: string;
                    title: string;
                },
            ) => Promise<TrayShowBalloonResponse>;
        };
        ui: {
            blur: () => Promise<WindowBlurResponse>;
            broadcast: (message: JsonValue) => Promise<WindowBroadcastResponse>;
            cancelClose: () => Promise<WindowCancelCloseResponse>;
            center: () => Promise<WindowCenterResponse>;
            clearClickThroughExcludeRegions: (
                windowId?: string,
            ) => Promise<WindowClearClickThroughExcludeRegionsResponse>;
            clearDragRegions: () => Promise<WindowClearDragRegionsResponse>;
            clearNoDragRegions: () => Promise<WindowClearNoDragRegionsResponse>;
            close: () => Promise<WindowCloseResponse>;
            closeAllPopups: () => Promise<WindowCloseAllPopupsResponse>;
            closePopup: (windowId: string) => Promise<WindowClosePopupResponse>;
            confirmClose: () => Promise<WindowConfirmCloseResponse>;
            createPopup: (
                opts: WindowCreatePopupOptions,
            ) => Promise<WindowCreatePopupResponse>;
            enterFullscreen: (
                windowId?: string,
            ) => Promise<WindowEnterFullscreenResponse>;
            exitFullscreen: (
                windowId?: string,
            ) => Promise<WindowExitFullscreenResponse>;
            flash: (opts: WindowFlashParams) => Promise<WindowFlashResponse>;
            flashTaskbar: (count?: number) => Promise<WindowFlashTaskbarResponse>;
            focus: (windowId?: string) => Promise<WindowFocusResponse>;
            getAllWindows: () => Promise<WindowListResponse>;
            getBackdropPolicy: (
                windowId?: string,
            ) => Promise<WindowGetBackdropPolicyResponse>;
            getBounds: () => Promise<WindowGetBoundsResponse>;
            getCaptionButtonsWidth: () => Promise<
                WindowGetCaptionButtonsWidthResponse,
            >;
            getCornerPreference: () => Promise<WindowGetCornerPreferenceResponse>;
            getCurrentWindowId: () => Promise<WindowGetCurrentWindowIdResponse>;
            getDevServerConfig: () => Promise<WindowGetDevServerConfigResponse>;
            getDpiScale: () => Promise<WindowGetDpiScaleResponse>;
            getMaxSize: (windowId?: string) => Promise<WindowGetMaxSizeResponse>;
            getMinSize: (windowId?: string) => Promise<WindowGetMinSizeResponse>;
            getMode: () => Promise<WindowGetModeResponse>;
            getPopupBehavior: (
                windowId?: string,
            ) => Promise<WindowGetPopupBehaviorResponse>;
            getState: () => Promise<WindowGetStateResponse>;
            getTitle: () => Promise<WindowGetTitleResponse>;
            getTitlebarHeight: () => Promise<WindowGetTitlebarHeightResponse>;
            getTitlebarInfo: () => Promise<WindowGetTitlebarInfoResponse>;
            getZoom: () => Promise<WindowGetZoomResponse>;
            hasSavedBounds: () => Promise<WindowHasSavedBoundsResponse>;
            isAlwaysOnTop: () => Promise<WindowIsAlwaysOnTopResponse>;
            isClickThrough: (
                windowId?: string,
            ) => Promise<WindowIsClickThroughResponse>;
            isFullscreen: (windowId?: string) => Promise<WindowIsFullscreenResponse>;
            isMaximized: () => Promise<WindowIsMaximizedResponse>;
            isMinimized: () => Promise<WindowIsMinimizedResponse>;
            isResizable: (windowId?: string) => Promise<WindowIsResizableResponse>;
            maximize: () => Promise<WindowMaximizeResponse>;
            minimize: () => Promise<WindowMinimizeResponse>;
            refreshWebView: () => Promise<WindowRefreshWebViewResponse>;
            reload: () => Promise<WindowReloadResponse>;
            resetZoom: () => Promise<WindowResetZoomResponse>;
            restore: () => Promise<WindowRestoreResponse>;
            sendMessage: (
                targetWindowId: string,
                message: JsonValue,
            ) => Promise<WindowSendMessageResponse>;
            setAcrylic: (
                opts: WindowSetAcrylicParams,
            ) => Promise<WindowSetAcrylicResponse>;
            setAlwaysOnTop: (
                enabled: boolean,
            ) => Promise<WindowSetAlwaysOnTopResponse>;
            setBackdropPolicy: (
                __namedParameters: WindowBackdropPolicyPatch & { windowId?: string },
            ) => Promise<WindowSetBackdropPolicyResponse>;
            setBackgroundTransparency: (
                opts: WindowSetBackgroundTransparencyParams,
            ) => Promise<WindowSetBackgroundTransparencyResponse>;
            setBlur: (opts: WindowSetBlurParams) => Promise<WindowSetBlurResponse>;
            setBounds: (
                __namedParameters: WindowSetBoundsParams,
            ) => Promise<WindowSetBoundsResponse>;
            setClickThrough: (
                opts: WindowSetClickThroughParams,
            ) => Promise<WindowSetClickThroughResponse>;
            setClickThroughExcludeRegions: (
                opts: WindowSetClickThroughExcludeRegionsParams,
            ) => Promise<WindowSetClickThroughExcludeRegionsResponse>;
            setCornerPreference: (
                mode: string,
            ) => Promise<WindowSetCornerPreferenceResponse>;
            setDarkMode: (
                enabled: boolean,
                windowId?: string,
            ) => Promise<WindowSetDarkModeResponse>;
            setDevServerConfig: (
                opts: WindowSetDevServerConfigParams,
            ) => Promise<WindowSetDevServerConfigResponse>;
            setDragRegions: (
                regions: WindowRegion[],
            ) => Promise<WindowSetDragRegionsResponse>;
            setFrameless: (
                frameless: boolean,
                windowId?: string,
            ) => Promise<WindowSetFramelessResponse>;
            setFullscreen: (
                enabled: boolean,
                windowId?: string,
            ) => Promise<WindowSetFullscreenResponse>;
            setMaximizeButtonRegion: (
                region?: WindowRegion,
            ) => Promise<WindowSetMaximizeButtonRegionResponse>;
            setMaxSize: (
                width: number,
                height: number,
                windowId?: string,
            ) => Promise<WindowSetMaxSizeResponse>;
            setMica: (opts?: WindowSetMicaParams) => Promise<WindowSetMicaResponse>;
            setMicaEffect: (
                opts?: WindowSetMicaEffectParams,
            ) => Promise<WindowSetMicaEffectResponse>;
            setMinSize: (
                width: number,
                height: number,
                windowId?: string,
            ) => Promise<WindowSetMinSizeResponse>;
            setNoDragRegions: (
                regions: WindowRegion[],
            ) => Promise<WindowSetNoDragRegionsResponse>;
            setPopupBehavior: (
                opts: WindowSetPopupBehaviorOptions,
            ) => Promise<WindowSetPopupBehaviorResponse>;
            setPosition: (x: number, y: number) => Promise<WindowSetPositionResponse>;
            setResizable: (
                resizable: boolean,
                windowId?: string,
            ) => Promise<WindowSetResizableResponse>;
            setSize: (width: number, height: number) => Promise<WindowSetSizeResponse>;
            setTitle: (title: string) => Promise<WindowSetTitleResponse>;
            setTitlebarHeight: (
                height: number,
            ) => Promise<WindowSetTitlebarHeightResponse>;
            setZoom: (zoom: number) => Promise<WindowSetZoomResponse>;
            setZoomForDpi: (dpi?: number) => Promise<WindowSetZoomForDpiResponse>;
            showContextMenu: (
                x?: number,
                y?: number,
            ) => Promise<UiShowContextMenuResponse>;
            showSystemMenu: (
                x: number,
                y: number,
                w?: number,
                h?: number,
            ) => Promise<WindowShowSystemMenuResponse>;
            startDrag: () => Promise<WindowStartDragResponse>;
            startResize: (edge: string) => Promise<WindowStartResizeResponse>;
            toggleAlwaysOnTop: () => Promise<WindowToggleAlwaysOnTopResponse>;
            toggleFullscreen: (
                windowId?: string,
            ) => Promise<WindowToggleFullscreenResponse>;
            toggleMaximize: () => Promise<WindowToggleMaximizeResponse>;
        };
        unwrap: {
            <R extends { success: boolean }>(response: R): Extract<R>;
            <R extends { success: boolean }, K extends string | number | symbol>(
                response: R,
                key: K,
            ): Extract<R, { success: true }>[K];
        };
        utils: {
            echo: (message: string) => Promise<TestEchoResponse>;
            formatTitle: (
                pattern: string,
                path?: string,
            ) => Promise<TitleformatEvalResponse>;
            getFileInfo: (path: string) => Promise<MetadataReadResponse>;
            ping: () => Promise<TestPingResponse>;
        };
        webview: { getSource: () => Promise<WebviewGetSourceResponse> };
    } = ...

    Aggregate runtime SDK surface. Provides the canonical window.fb shape used by themes and SMP-compatible scripts.

    • fb.player, fb.playlist, fb.library, ... — namespace proxies.
    • fb.on / fb.off / fb.once — typed event subscription.
    • fb.invoke — escape hatch for un-namespaced API calls.
    • fb.state — synchronous playback state mirror.
    • fb.isAvailable() / fb.ready() — availability probes.
    • fb.unwrap / fb.ApiCallError — turn a failure envelope into an exception.
    • fb.PlaybackClock — the playback position between the host's updates.

    Type Declaration

    • ApiCallError: typeof ApiCallError
    • artwork: {
          getAvailableArtwork: (
              path: string,
          ) => Promise<ArtworkGetAvailableArtworkResponse>;
          getAvailableTypes: (
              path?: string,
          ) => Promise<ArtworkGetAvailableTypesResponse>;
          getBatch: (
              paths: string[],
              type?: AlbumArtType,
          ) => Promise<ArtworkGetBatchResponse>;
          getByPath: (
              path: string,
              type?: AlbumArtType,
          ) => Promise<ArtworkGetByPathResponse>;
          getByPlaylistItem: (
              playlist: PlaylistRef,
              index: number,
              type?: AlbumArtType,
          ) => Promise<ArtworkGetByPlaylistItemResponse>;
          getCurrent: (type?: AlbumArtType) => Promise<ArtworkGetCurrentResponse>;
          getFb2kUrl: (
              type?: AlbumArtType,
              options?: Pick<ArtworkGetFb2kUrlParams, "maxSize">,
          ) => Promise<ArtworkGetFb2kUrlResponse>;
          getFb2kUrlByPath: (
              path: string,
              type?: AlbumArtType,
              options?: Pick<ArtworkGetFb2kUrlByPathParams, "maxSize">,
          ) => Promise<ArtworkGetFb2kUrlByPathResponse>;
          getFb2kUrlByPathBatch: (
              items: string[] | ArtworkBatchItem[],
              opts?: { maxSize?: number; type?: AlbumArtType },
          ) => Promise<ArtworkGetFb2kUrlByPathBatchResponse>;
          getFolderImages: (
              directory: string,
          ) => Promise<ArtworkGetFolderImagesResponse>;
          getForTrack: (
              path: string,
              type?: AlbumArtType,
              options?: ArtworkOptions,
          ) => Promise<ArtworkGetForTrackResponse>;
          getLyrics: (path?: string) => Promise<ArtworkGetLyricsResponse>;
          getMetadata: (path?: string) => Promise<ArtworkGetMetadataResponse>;
          withMaxSize: (url: string, maxSize?: number) => string;
      }

      artwork — album art retrieval namespace.

      Every reader answers with the host's success envelope. available tells whether a picture (or a URL) exists for the request; a refused call has success: false with a code.

    • audio: {
          analyzeBPM: (path: string) => Promise<AudioAnalyzeBPMResponse>;
          cancelDecodePcm: (taskId: string) => Promise<AudioCancelDecodePcmResponse>;
          cancelFullWaveform: (
              taskId: string,
          ) => Promise<AudioCancelFullWaveformResponse>;
          decodePcm: (path: string, opts?: DecodePcmOptions) => Promise<PcmBuffer>;
          generateFullWaveform: (
              path: string,
              opts?: FullWaveformOptions & { signal?: AbortSignal; timeout?: number },
          ) => Promise<FullWaveformResult>;
          getOutputInfo: () => Promise<AudioGetOutputInfoResponse>;
          getPcmDebugState: () => Promise<AudioGetPcmDebugStateResponse>;
          getSpectrum: (
              options?: AudioGetSpectrumParams,
          ) => Promise<AudioGetSpectrumResponse>;
          getSpectrumDebugState: () => Promise<AudioGetSpectrumDebugStateResponse>;
          getStreamInfo: () => Promise<AudioGetStreamInfoResponse>;
          getWaveform: (
              pathOrOpts?: string | AudioGetWaveformParams,
              opts?: AudioGetWaveformParams,
          ) => Promise<AudioGetWaveformResponse>;
          isVisualizationAvailable: () => Promise<
              AudioIsVisualizationAvailableResponse,
          >;
          setChannelMode: (
              mode: NonNullable<"default" | "back" | "front" | "mono" | undefined>,
          ) => Promise<AudioSetChannelModeResponse>;
          subscribeSpectrum: SpectrumSubscribeFunction;
          subscribeStream: (opts?: PcmStreamOptions) => PcmStream;
          unsubscribeStream: (
              subscriptionId?: string,
          ) => Promise<AudioUnsubscribeStreamResponse>;
      }

      audio — real-time audio analysis namespace.

      Spectrum / waveform subscriptions return an unsubscribe callback; call it to stop receiving callbacks and notify the host so the underlying compute pipeline is torn down.

      audio.generateFullWaveform resolves either synchronously (cache hit) or asynchronously by listening for the audio:fullWaveformReady / audio:fullWaveformFailed events with a client-side timeout; a timeout or an aborted signal also cancels the host task.

      • analyzeBPM: (path: string) => Promise<AudioAnalyzeBPMResponse>

        Read the track's BPM tag; the host does not detect tempo. Resolves success: false with code: 'NOT_FOUND' when the tag is missing or is not a number between 0 and 500 (exclusive).

      • ExperimentalcancelDecodePcm: (taskId: string) => Promise<AudioCancelDecodePcmResponse>

        Cancel a pending audio.decodePcm task by its taskId. The SDK's audio.decodePcm does this for you on abort and timeout; call it directly only for tasks started with a raw invoke. cancelled: false means the task has already settled, does not exist or belongs to another page.

      • cancelFullWaveform: (taskId: string) => Promise<AudioCancelFullWaveformResponse>

        Cancel a pending audio.generateFullWaveform request by the taskId of its pending answer. Only the caller that made the request can cancel it: cancelled: false means the task has already settled, does not exist or belongs to another caller. A cancelled task receives one audio:fullWaveformFailed with code: 'CANCELLED', which may arrive before this answer.

      • ExperimentaldecodePcm: (path: string, opts?: DecodePcmOptions) => Promise<PcmBuffer>

        Decode a track, or a range of it, into float32 PCM and resolve with a PcmBuffer that reads the samples in place.

        The samples live in read-only shared memory: writing through getChannelView() crashes the renderer process, so copy them with toAudioBuffer() when you need to change them, and call release() when done. One task decodes at a time and the rest queue; identical requests in flight share one decode.

        Rejects with PcmDecodeError carrying the host's code when the host refuses the request (INVALID_PARAMS also covers a range too large for one buffer: 256 MiB in 64-bit foobar2000, 64 MiB in 32-bit) or the task fails later; NOT_SUPPORTED outside a WebView2 host. opts.signal and opts.timeoutMs (default 120 s, 0 waits forever) cancel the host task and reject, with an AbortError DOMException and code TIMEOUT respectively.

        const pcm = await fb.audio.decodePcm(path, { start: 30, end: 60, sampleRate: 22050, mono: true });
        try {
        analyse(pcm.getChannelView(0), pcm.sampleRate);
        } finally {
        pcm.release();
        }
        @experimental
      • generateFullWaveform: (
            path: string,
            opts?: FullWaveformOptions & { signal?: AbortSignal; timeout?: number },
        ) => Promise<FullWaveformResult>

        Generate a full-track waveform. Resolves synchronously on cache hit; otherwise awaits the audio:fullWaveformReady / audio:fullWaveformFailed events.

        opts.timeout (default 60 s, 0 waits forever) and opts.signal end the wait early and cancel the host task through audio.cancelFullWaveform; neither is sent to the host. An aborted signal rejects with a DOMException named AbortError, a timeout with { success: false, error: 'TIMEOUT' }. A cache hit resolves whatever the signal does.

        Failures take three shapes: a request the host refuses up front (bad path, permission, shutdown) resolves with { success: false, error, code }; a decode that fails later rejects with the audio:fullWaveformFailed payload; a bridge-level error rejects with an Error. The host decodes two tracks at a time and queues the rest; time spent in its queue counts toward the timeout.

      • getOutputInfo: () => Promise<AudioGetOutputInfoResponse>

        Report foobar2000's volume and output information.

      • ExperimentalgetPcmDebugState: () => Promise<AudioGetPcmDebugStateResponse>

        Shared-buffer support of this page and the state of the decode queue, for tests and diagnostics.

      • getSpectrum: (options?: AudioGetSpectrumParams) => Promise<AudioGetSpectrumResponse>

        Single-shot poll of the spectrum; requires at least one active audio.subscribeSpectrum subscription on the host side. With subscriptionId the frame uses that subscription's parameters. Paused or stopped playback answers with a silence frame; a stream that has not produced data yet answers success: false.

      • getSpectrumDebugState: () => Promise<AudioGetSpectrumDebugStateResponse>

        Report the spectrum runtime state as the host sees it, for diagnostics.

      • getStreamInfo: () => Promise<AudioGetStreamInfoResponse>

        Report the audio format of the playing track.

      • getWaveform: (
            pathOrOpts?: string | AudioGetWaveformParams,
            opts?: AudioGetWaveformParams,
        ) => Promise<AudioGetWaveformResponse>

        Short-window waveform of the current playback stream. Accepts either (opts) (preferred) or (path, opts) (deprecated form; the path is ignored because the host always uses the active stream).

      • isVisualizationAvailable: () => Promise<AudioIsVisualizationAvailableResponse>

        Report whether foobar2000 provides an active visualization stream.

      • setChannelMode: (
            mode: NonNullable<"default" | "back" | "front" | "mono" | undefined>,
        ) => Promise<AudioSetChannelModeResponse>

        Choose the channels of the visualisation stream behind spectrum frames and getWaveform; what is heard does not change.

      • subscribeSpectrum: SpectrumSubscribeFunction

        Subscribe to a real-time spectrum stream. The callback receives this subscription's frames only; other subscriptions on the same event name get their own.

        With output: 'bins' the callback receives the FFT's linear bins as power in dB (see SpectrumOutput); band output is kept for compatibility. A host without bin output registers band output instead: ready then reports output: 'bands' and the callback receives nothing.

        Returns an unsubscribe callback that detaches the listener and removes the subscription on the host. Its ready promise settles with the host's answer to the registration (ok: false with INVALID_PARAMS for rejected parameters) and never rejects.

        const stop = fb.audio.subscribeSpectrum((frame) => {
        const values = frame.channels === 'stereo' ? frame.left : frame.spectrum;
        draw(frame.firstBin, values);
        }, { output: 'bins', fftSize: 16384, backgroundThrottle: false });
        const outcome = await stop.ready;
        if (!outcome.ok || outcome.output !== 'bins') console.warn('no bin output');
      • ExperimentalsubscribeStream: (opts?: PcmStreamOptions) => PcmStream

        Subscribe to the audio foobar2000 is playing and get a PcmStream to poll for frames.

        The samples are what the DSP chain produces, before ReplayGain and the volume control, so they differ from audio:spectrum in not including ReplayGain. They live in read-only shared memory; read() copies them out per channel and reports frames the ring overwrote before they were read. Nothing arrives while playback is stopped or paused. Poll from requestAnimationFrame or a timer and call unsubscribe() when done.

        opts.interval asks the core for a callback interval in seconds; the core rounds it to about 16 ms steps, never exceeds 200 ms (its default), and applies the shortest interval any subscription in the component asked for. opts.bufferSeconds sizes the ring (default 1 s; the first chunk after playback starts can hold up to 0.8 s of audio).

        The handle's ready resolves with the host's answer and never rejects; code is NOT_SUPPORTED outside a WebView2 host or on a runtime without shared buffers, OPERATION_FAILED when the page already has 8 stream subscriptions.

        const stream = fb.audio.subscribeStream({ bufferSeconds: 0.5 });
        const tick = () => {
        const chunk = stream.read();
        if (chunk) meter.push(chunk.planes[0], chunk.dropped);
        if (!stream.ended) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
        @experimental
      • ExperimentalunsubscribeStream: (subscriptionId?: string) => Promise<AudioUnsubscribeStreamResponse>

        Remove this page's stream subscriptions on the host: the one with subscriptionId, or all of them when omitted. PcmStream.unsubscribe does this for its own subscription; call this directly only for subscriptions made with a raw invoke. Resolves with the number removed.

    • canPlay: (
          track: ContainerTrack,
          limits?: MediaVideoDecodingLimits,
      ) => Promise<MediaCanPlayResult>
    • clipboard: {
          read: () => Promise<ClipboardReadResponse>;
          write: (text: string) => Promise<ClipboardWriteResponse>;
          writeFiles: (paths: string[]) => Promise<ClipboardWriteFilesResponse>;
          writeHTML: (
              html: string,
              plainText?: string,
          ) => Promise<ClipboardWriteHTMLResponse>;
      }

      clipboard — clipboard read/write namespace.

      • read: () => Promise<ClipboardReadResponse>

        Report what the Windows clipboard holds: text, file list, or image.

      • write: (text: string) => Promise<ClipboardWriteResponse>

        Replace the clipboard contents with Unicode text.

      • writeFiles: (paths: string[]) => Promise<ClipboardWriteFilesResponse>

        Place a file list on the clipboard (CF_HDROP) for Explorer and other shell targets to paste.

      • writeHTML: (html: string, plainText?: string) => Promise<ClipboardWriteHTMLResponse>

        Replace the clipboard contents with rich text in HTML format, plus a plain-text fallback.

    • config: {
          export: () => Promise<ConfigExportResponse>;
          get: (key: string, defaultValue?: JsonValue) => Promise<ConfigGetResponse>;
          getActiveDspPreset: () => Promise<ConfigGetActiveDspPresetResponse>;
          getAdvancedConfig: (
              parentGuid?: string,
          ) => Promise<ConfigGetAdvancedConfigResponse>;
          getAdvancedConfigValue: (
              guid: string,
          ) => Promise<ConfigGetAdvancedConfigValueResponse>;
          getAll: () => Promise<ConfigGetAllResponse>;
          getComponents: () => Promise<ConfigGetComponentsResponse>;
          getCursorFollowPlayback: () => Promise<
              ConfigGetCursorFollowPlaybackResponse,
          >;
          getDspPresets: () => Promise<ConfigGetDspPresetsResponse>;
          getLibraryFilePatterns: () => Promise<ConfigGetLibraryFilePatternsResponse>;
          getLibraryStatus: () => Promise<ConfigGetLibraryStatusResponse>;
          getOutputConfig: () => Promise<ConfigGetOutputConfigResponse>;
          getOutputDevices: () => Promise<ConfigGetOutputDevicesResponse>;
          getPlaybackFollowCursor: () => Promise<
              ConfigGetPlaybackFollowCursorResponse,
          >;
          getPreferencesPages: () => Promise<ConfigGetPreferencesPagesResponse>;
          getPreferencesStandardGuids: () => Promise<
              ConfigGetPreferencesStandardGuidsResponse,
          >;
          getReplaygainMode: () => Promise<ConfigGetReplaygainModeResponse>;
          getVersionInfo: () => Promise<ConfigGetVersionInfoResponse>;
          remove: (key: string) => Promise<ConfigRemoveResponse>;
          resetAdvancedConfig: (
              guid: string,
          ) => Promise<ConfigResetAdvancedConfigResponse>;
          set: (key: string, value: JsonValue) => Promise<ConfigSetResponse>;
          setActiveDspPreset: (
              index: number,
          ) => Promise<ConfigSetActiveDspPresetResponse>;
          setAdvancedConfigValue: (
              guid: string,
              value: JsonValue,
          ) => Promise<ConfigSetAdvancedConfigValueResponse>;
          setCursorFollowPlayback: (
              enabled: boolean,
          ) => Promise<ConfigSetCursorFollowPlaybackResponse>;
          setOutputBuffer: {
              (ms: number): Promise<ConfigSetOutputBufferResponse>;
              (
                  opts: ConfigSetOutputBufferParams,
              ): Promise<ConfigSetOutputBufferResponse>;
          };
          setOutputDevice: (
              outputId: string,
              deviceId: string,
          ) => Promise<ConfigSetOutputDeviceResponse>;
          setPlaybackFollowCursor: (
              enabled: boolean,
          ) => Promise<ConfigSetPlaybackFollowCursorResponse>;
          setReplaygainMode: (
              mode: ReplaygainSourceMode | ReplaygainSourceModeName,
          ) => Promise<ConfigSetReplaygainModeResponse>;
          showLibraryPreferences: () => Promise<ConfigShowLibraryPreferencesResponse>;
      }

      config — output / DSP / advanced / portable-config namespace.

      • export: () => Promise<ConfigExportResponse>

        Read the whole store both as a map and as one JSON text.

      • get: (key: string, defaultValue?: JsonValue) => Promise<ConfigGetResponse>

        Reads the value stored under key. A key that is not stored is not an error: the response has found: false and value set to defaultValue, or null when no default is given.

      • getActiveDspPreset: () => Promise<ConfigGetActiveDspPresetResponse>

        Report which DSP preset is selected.

      • getAdvancedConfig: (parentGuid?: string) => Promise<ConfigGetAdvancedConfigResponse>

        foobar2000's Advanced preferences from the root, or from below parentGuid, in entries; each branch has its entries nested in children.

      • getAdvancedConfigValue: (guid: string) => Promise<ConfigGetAdvancedConfigValueResponse>

        Read one Advanced preferences entry by GUID.

      • getAll: () => Promise<ConfigGetAllResponse>

        Full snapshot of the portable-config cache. Returns the { success, items, configs, count } envelope; items and configs are interchangeable aliases of the same map.

      • getComponents: () => Promise<ConfigGetComponentsResponse>

        The installed components, in components.

      • getCursorFollowPlayback: () => Promise<ConfigGetCursorFollowPlaybackResponse>

        Report foobar2000's "cursor follows playback" setting.

      • getDspPresets: () => Promise<ConfigGetDspPresetsResponse>

        The stored DSP presets, in presets.

      • getLibraryFilePatterns: () => Promise<ConfigGetLibraryFilePatternsResponse>

        Each pattern is present only when foobar2000 has it configured, so with neither configured the response is { success: true } alone.

      • getLibraryStatus: () => Promise<ConfigGetLibraryStatusResponse>

        Report whether the media library is enabled and loaded, and how many items it holds.

      • getOutputConfig: () => Promise<ConfigGetOutputConfigResponse>

        Report the output settings in effect: module, device, buffer length, bit depth, dithering and fades.

      • getOutputDevices: () => Promise<ConfigGetOutputDevicesResponse>

        The devices of every output module, in devices, flagged when one is in effect.

      • getPlaybackFollowCursor: () => Promise<ConfigGetPlaybackFollowCursorResponse>

        Report foobar2000's "playback follows cursor" setting.

      • getPreferencesPages: () => Promise<ConfigGetPreferencesPagesResponse>

        Every preferences page, then every preferences branch, in pages.

      • getPreferencesStandardGuids: () => Promise<ConfigGetPreferencesStandardGuidsResponse>

        Report the GUIDs of foobar2000's standard preferences parents.

      • getReplaygainMode: () => Promise<ConfigGetReplaygainModeResponse>

        Resolve the active ReplayGain source mode.

        The host returns the mode as an integer (0 = none, 1 = track, 2 = album, 3 = byPlaybackOrder). Use the REPLAYGAIN_SOURCE_MODE constant dictionary exported alongside the response type to compare against named entries:

        const r = await config.getReplaygainMode();
        if (r.mode === REPLAYGAIN_SOURCE_MODE.track) { ... }
        

        The value field is an alias of mode retained for compatibility with older host builds.

      • getVersionInfo: () => Promise<ConfigGetVersionInfoResponse>

        Report the foobar2000 version, this component's version and the profile folder.

      • remove: (key: string) => Promise<ConfigRemoveResponse>

        Delete a key from the component's configuration store.

      • resetAdvancedConfig: (guid: string) => Promise<ConfigResetAdvancedConfigResponse>

        Return one Advanced preferences entry to its default value.

      • set: (key: string, value: JsonValue) => Promise<ConfigSetResponse>

        Stores any JSON value under key. A top-level null is refused with an INVALID_PARAMS failure envelope; clear a key with config.remove instead.

      • setActiveDspPreset: (index: number) => Promise<ConfigSetActiveDspPresetResponse>

        Select a preset by its index from config.getDspPresets. An index past the end resolves with an INVALID_INDEX failure envelope.

      • setAdvancedConfigValue: (
            guid: string,
            value: JsonValue,
        ) => Promise<ConfigSetAdvancedConfigValueResponse>

        Write one Advanced preferences entry: a boolean for a checkbox or radio entry, a string or a number for a string or integer entry. A value of the wrong kind resolves with an INVALID_PARAMS failure envelope.

      • setCursorFollowPlayback: (enabled: boolean) => Promise<ConfigSetCursorFollowPlaybackResponse>

        Turn foobar2000's "cursor follows playback" setting on or off.

      • setOutputBuffer: {
            (ms: number): Promise<ConfigSetOutputBufferResponse>;
            (opts: ConfigSetOutputBufferParams): Promise<ConfigSetOutputBufferResponse>;
        }

        Set the output buffer length.

        Accepts either a single numeric argument (milliseconds, matching the original (ms) signature) or an options object that lets callers pick the unit explicitly:

        • milliseconds — buffer in ms, from 50 to 2000.
        • bufferLength — buffer in seconds (the host's native unit), from 0.05 to 2.

        If both fields are present the host uses milliseconds, though it still refuses a bufferLength outside its range. Out-of-range values and a call with neither field resolve with an INVALID_PARAMS failure envelope.

        Numeric milliseconds, or an options object with milliseconds and/or bufferLength.

      • setOutputDevice: (outputId: string, deviceId: string) => Promise<ConfigSetOutputDeviceResponse>

        Switch output to a device of an output module; take both GUIDs from config.getOutputDevices.

      • setPlaybackFollowCursor: (enabled: boolean) => Promise<ConfigSetPlaybackFollowCursorResponse>

        Turn foobar2000's "playback follows cursor" setting on or off.

      • setReplaygainMode: (
            mode: ReplaygainSourceMode | ReplaygainSourceModeName,
        ) => Promise<ConfigSetReplaygainModeResponse>

        Set the active ReplayGain source mode.

        Accepts either an integer (0-3, see REPLAYGAIN_SOURCE_MODE), sent as mode, or a name, sent as sourceMode ('none' | 'track' | 'album' | 'byPlaybackOrder' | 'auto'). 'auto' is treated by the host as an alias of 'byPlaybackOrder' and yields integer mode 3.

      • showLibraryPreferences: () => Promise<ConfigShowLibraryPreferencesResponse>

        Open foobar2000's Media Library preferences page.

    • Readonlyconsole: {
          error: (
              message: string,
              ...args: JsonValue[],
          ) => Promise<ConsoleErrorResponse>;
          log: (message: string, ...args: JsonValue[]) => Promise<ConsoleLogResponse>;
          warn: (
              message: string,
              ...args: JsonValue[],
          ) => Promise<ConsoleWarnResponse>;
      }
      • error: (message: string, ...args: JsonValue[]) => Promise<ConsoleErrorResponse>

        Writes an error line prefixed with [WebView][ERROR].

      • log: (message: string, ...args: JsonValue[]) => Promise<ConsoleLogResponse>

        Writes a line prefixed with [WebView].

      • warn: (message: string, ...args: JsonValue[]) => Promise<ConsoleWarnResponse>

        Writes a warning line prefixed with [WebView][WARN].

    • cursor: {
          isHidden: () => Promise<CursorIsHiddenResponse>;
          setHidden: (hidden: boolean) => Promise<CursorSetHiddenResponse>;
      }

      cursor — explicit client-area cursor visibility control.

      Companion to src/api/CursorApi.cpp. Visual Hosting (CompositionController) leaves the WebView2 without an HWND of its own — WM_SETCURSOR is dispatched to the parent foobar2000 frame and Chromium's CursorChanged callback cannot reflect a CSS cursor: none rule reliably. Themes that want idle-hide behaviour (full-screen players, desktop-lyrics overlays) drive the host directly through this namespace.

      State is per-window: each popup tracks its own hidden flag and the cursor:hiddenChanged event is routed only to the originating window.

      • isHidden: () => Promise<CursorIsHiddenResponse>

        Read the current hidden state for the calling window. Reports hidden: false when the caller window cannot be resolved.

      • setHidden: (hidden: boolean) => Promise<CursorSetHiddenResponse>

        Hide or restore the calling window's client-area cursor.

        Repeated calls with the same hidden value resolve with success: true, changed: false — only flips that actually move the visibility flag emit a follow-up cursor:hiddenChanged event. When the host cannot resolve the calling window the call fails with code: 'OPERATION_FAILED'.

    • dialog: {
          confirm: (opts?: DialogConfirmParams) => Promise<DialogConfirmResponse>;
          openFile: (opts?: DialogOpenFileParams) => Promise<DialogOpenFileResponse>;
          openFolder: (
              opts?: DialogOpenFolderParams,
          ) => Promise<DialogOpenFolderResponse>;
          saveFile: (opts?: DialogSaveFileParams) => Promise<DialogSaveFileResponse>;
      }

      dialog — file/folder pickers + confirm/prompt.

      • confirm: (opts?: DialogConfirmParams) => Promise<DialogConfirmResponse>

        Shows a modal confirmation dialog.

        Resolves with { response }, the zero-based index of the clicked button in buttons. The default button set is ['OK', 'Cancel'], so 0 means confirmed and 1 means cancelled - there is no confirmed flag. The task dialog is created without TDF_ALLOW_DIALOG_CANCELLATION, so Escape and the close button do not dismiss it and every result comes from an actual button click. -1 appears only on the host's fallback path, when even a plain message box could not be shown.

      • openFile: (opts?: DialogOpenFileParams) => Promise<DialogOpenFileResponse>

        Resolves with { success: true, canceled, filePaths }; filePaths is empty when cancelled. When the dialog cannot be shown at all it resolves with the failure envelope { success: false, error, code } instead.

      • openFolder: (opts?: DialogOpenFolderParams) => Promise<DialogOpenFolderResponse>

        Resolves like openFile, with folderPath (empty when cancelled) in place of filePaths.

      • saveFile: (opts?: DialogSaveFileParams) => Promise<DialogSaveFileResponse>

        Resolves like openFile, with filePath (empty when cancelled) in place of filePaths.

    • discovery: {
          executeContextMenuByPath: (
              opts: DiscoveryExecuteContextMenuByPathParams,
          ) => Promise<DiscoveryExecuteContextMenuByPathResponse>;
          executeContextMenuCommand: (
              opts: DiscoveryExecuteContextMenuCommandParams,
          ) => Promise<DiscoveryExecuteContextMenuCommandResponse>;
          executeMainMenuCommand: (
              guid: string,
              subGuid?: string,
          ) => Promise<DiscoveryExecuteMainMenuCommandResponse>;
          getAllServices: () => Promise<DiscoveryGetAllServicesResponse>;
          getComponents: () => Promise<DiscoveryGetComponentsResponse>;
          getContextMenuCommands: (
              opts?: DiscoveryGetContextMenuCommandsParams,
          ) => Promise<DiscoveryGetContextMenuCommandsResponse>;
          getContextMenuTree: () => Promise<DiscoveryGetContextMenuTreeResponse>;
          getDspEntries: () => Promise<DiscoveryGetDspEntriesResponse>;
          getInputFormats: () => Promise<DiscoveryGetInputFormatsResponse>;
          getMainMenuCommands: (
              opts?: DiscoveryGetMainMenuCommandsParams,
          ) => Promise<DiscoveryGetMainMenuCommandsResponse>;
          getMainMenuGroups: () => Promise<DiscoveryGetMainMenuGroupsResponse>;
          getOutputDevices: () => Promise<DiscoveryGetOutputDevicesResponse>;
          getPreferencePages: () => Promise<DiscoveryGetPreferencePagesResponse>;
          getUIElements: () => Promise<DiscoveryGetUIElementsResponse>;
          searchCommands: (
              query: string,
              opts?: Omit<DiscoverySearchCommandsParams, "query">,
          ) => Promise<DiscoverySearchCommandsResponse>;
      }

      discovery — service / menu / component discovery namespace.

      • executeContextMenuByPath: (
            opts: DiscoveryExecuteContextMenuByPathParams,
        ) => Promise<DiscoveryExecuteContextMenuByPathResponse>

        Executes a context-menu command addressed by its display path, e.g. 'Playback Statistics/Rating/5'.

        Each path segment must match a menu label exactly once, after normalization (mnemonic &, a trailing ellipsis, accelerator text and ASCII case are ignored). Matching is never a substring test, so 'Rating/1' cannot resolve to 'Rating/10'.

        A path that matches several commands is refused instead of guessed — duplicated labels are common in real hosts. That failure carries match: 'ambiguous' and a candidates list of full names; use it to refine the path, or address the command by GUID via executeContextMenuCommand, which is the only stable identifier. target picks the tracks as for that method; it cannot be combined with trackPath.

      • executeContextMenuCommand: (
            opts: DiscoveryExecuteContextMenuCommandParams,
        ) => Promise<DiscoveryExecuteContextMenuCommandResponse>

        Executes a context-menu command by GUID against the tracks target names. The default, 'auto', is the playing track, or the active playlist selection when nothing is playing; 'selection' matches what foobar2000's own context-menu shortcuts act on.

        A FORCE_OFF command is refused rather than dispatched: the SDK treats that state as "keyboard-shortcut list only", so the host never draws it and running it would perform something the user could not have clicked. The refusal fails with NOT_SUPPORTED and carries hidden: true. Pass { force: true } to dispatch anyway. DEFAULT_OFF commands (hidden unless Shift is held) are still invocable and are never refused. When the target holds no track the call fails with NO_ACTIVE_ITEM.

      • executeMainMenuCommand: (
            guid: string,
            subGuid?: string,
        ) => Promise<DiscoveryExecuteMainMenuCommandResponse>

        Execute a main-menu command. For a command expanded from a dynamic submenu, pass the entry's subGuid as well. Dynamic containers and incomplete addresses are refused; the current leaf must have a unique owner and be enabled. A missing GUID fails with NOT_FOUND.

      • getAllServices: () => Promise<DiscoveryGetAllServicesResponse>

        Count the discoverable service families in the running process.

      • getComponents: () => Promise<DiscoveryGetComponentsResponse>

        List the installed components.

      • getContextMenuCommands: (
            opts?: DiscoveryGetContextMenuCommandsParams,
        ) => Promise<DiscoveryGetContextMenuCommandsResponse>

        Lists context-menu commands with their state.

        enabled / checked are only observable when a track is selected or playing, because the SDK evaluates display data against a track set. Check the response's stateKnown before trusting them: when it is false, only hidden is meaningful. FORCE_OFF entries are shortcut-list-only per the SDK and are omitted unless includeHidden is set.

      • getContextMenuTree: () => Promise<DiscoveryGetContextMenuTreeResponse>

        Dumps the full context-menu tree for the current selection (or the playing track), as the host would build it.

        The walk is bounded in depth and in children per node, and any clipping is reported rather than silent: check truncated on the response for the whole tree, or on an individual node for its subtree. A popup node carries both childCount (the host's real count) and childrenReturned (what this response contains) so the two can be reconciled without counting.

      • getDspEntries: () => Promise<DiscoveryGetDspEntriesResponse>

        List the registered DSP entries.

      • getInputFormats: () => Promise<DiscoveryGetInputFormatsResponse>

        List the playable input file types, each with a display name and a filename mask.

      • getMainMenuCommands: (
            opts?: DiscoveryGetMainMenuCommandsParams,
        ) => Promise<DiscoveryGetMainMenuCommandsResponse>

        List main-menu commands. Components that build their submenu at runtime (mainmenu_commands_v2, e.g. ESLyric) are expanded by default, so the result includes their child commands in addition to the parent slot. Pass { expandDynamic: false } for the raw static registry only.

        Entries the host would not show — a command whose get_display() returns false, or one carrying flag_defaulthidden — are omitted by default, because they are not reachable from the real menu. Pass { includeHidden: true } to get the unfiltered superset.

      • getMainMenuGroups: () => Promise<DiscoveryGetMainMenuGroupsResponse>

        List the groups main-menu commands are filed under.

      • getOutputDevices: () => Promise<DiscoveryGetOutputDevicesResponse>

        List the registered output backends by GUID.

      • getPreferencePages: () => Promise<DiscoveryGetPreferencePagesResponse>

        List the pages of the Preferences dialog.

      • getUIElements: () => Promise<DiscoveryGetUIElementsResponse>

        List the registered UI elements.

      • searchCommands: (
            query: string,
            opts?: Omit<DiscoverySearchCommandsParams, "query">,
        ) => Promise<DiscoverySearchCommandsResponse>

        Case-insensitive substring search over command names, descriptions and menu paths, across both menu families.

        Each hit carries type ('mainmenu' / 'contextmenu') plus the same state fields the enumeration endpoints return, so a caller can tell whether a hit is invocable without a second round trip. Pass { scope: 'mainmenu' } or { scope: 'contextmenu' } to search one family only.

        Entries the host would not show are excluded, matching the enumeration endpoints; pass { includeHidden: true } for the unfiltered superset. Dynamic submenus are expanded by default — pass { expandDynamic: false } for the static registry only.

        Context-menu state is only observable with a track selected or playing. When the context family was searched without one, the response's stateKnown is false and its hits' enabled / checked must not be filtered on.

    • dnd: {
          applyDragToken: (dataTransfer: DataTransfer, token: string) => void;
          getCapabilities: () => Promise<DndGetCapabilitiesResponse>;
          getPaths: () => string[];
          getPathsAsync: (sessionId?: string) => Promise<DndGetPathsAsyncResponse>;
          getResolvedPaths: () => (string | null)[];
          hasFiles: () => boolean;
          onDragEnded: (
              handler: (payload: DndDragEndedPayload) => void,
          ) => () => void;
          prepareDrag: (paths: string[]) => Promise<DndPrepareDragResponse>;
          startDrag: (_type?: string) => Promise<DndStartDragResponse>;
      }

      dnd — external file drop.

      Windows hands a dropped file list to the native window, not to the page, and the HTML5 File object deliberately hides its filesystem path. This namespace exposes the host's own view of a drag session so a page can obtain real paths and pass them to playlist or library calls.

      Three ways to read paths, in decreasing reliability:

      1. dnd.getPathsAsync — queries the host directly. Use this inside a HTML5 drop handler.
      2. The dnd:drop event payload — authoritative, but arrives on its own schedule relative to the page's drop handler.
      3. dnd.getPaths — synchronous snapshot read. Best-effort only.

      A dragged shortcut puts the .lnk file itself in the list, which foobar2000 cannot play, so every path source above is joined by a parallel array of shortcut targets: resolvedPaths on the payloads and on dnd.getPathsAsync, and dnd.getResolvedPaths for the snapshot.

      A drop lands only where the page accepts it by calling preventDefault() in its HTML5 dragover handler. Elsewhere the host refuses it: the cursor shows "forbidden" and no dnd:drop follows, except for a drop released in the first half second, before the page has answered.

      Paths are withheld from untrusted origins. Standard HTML5 drag events keep working in that case, so check dnd.getCapabilities before showing UI that depends on paths.

      The page-side snapshot is published to the top-level document only, so dnd.getPaths and dnd.getResolvedPaths answer with an empty array inside an <iframe>. A framed page that needs paths has to receive them from the main frame over postMessage.

      The reverse direction, dragging tracks OUT of the window into Explorer or another application, goes through dnd.prepareDrag and dnd.applyDragToken; see those for the handshake.

      • applyDragToken: (dataTransfer: DataTransfer, token: string) => void

        Writes a drag token into a dragstart event's data transfer so the host attaches the token's files to the drag.

        Must run synchronously inside the dragstart handler. It sets the text/plain entry to the token carrier, replacing anything the page put there, and sets effectAllowed to 'copy'. Both are required: the host identifies a drag-out by that text/plain marker, and it attaches no files to a drag whose allowed effects are wider than copy, because a drop target given a move effect would relocate the user's files. Do not change effectAllowed afterwards.

        The text/plain slot is therefore not available for page text during a drag-out. Text-oriented drop targets receive an empty string, never the token.

        Once the host accepts the token, the drag proceeds like any other page drag: it draws the drag image, and the page's dragend reports the outcome through dataTransfer.dropEffect. When the host refuses the token or the effects, the drag still proceeds, as a page drag carrying no files, and dnd:dragEnded says why. While a drag is in progress the host window waits for the drop target, exactly as it does for a plain HTML5 drag.

      • getCapabilities: () => Promise<DndGetCapabilitiesResponse>

        What this window's drag-drop integration can currently deliver.

        Not constant for the window's lifetime: navigating to a different origin, or Chromium re-registering its own drop target, can withdraw path access while leaving HTML5 drag events intact. Subscribe to dnd:capabilitiesChanged to react to that.

      • getPaths: () => string[]

        Paths of the current drag session from the page-side snapshot.

        Synchronous and therefore best-effort: returns an empty array when no session is active, when the drag carries no file list, when the origin is not trusted with paths, or when the host has not published the session yet. A fast drag can reach the page's drop handler before publication completes, so do not use this as the only source of paths — prefer dnd.getPathsAsync and keep this for optimistic UI.

      • getPathsAsync: (sessionId?: string) => Promise<DndGetPathsAsyncResponse>

        Queries the host for a drag session's real filesystem paths.

        The reliable way to obtain paths from inside a HTML5 drop handler: it reads the host's session state rather than a snapshot pushed to the page, so it does not depend on message delivery order. Safe to call after await, since it never touches event.dataTransfer.

        Paths come back in the same order as DataTransfer.files, so a page can pair them by index. resolvedPaths carries the .lnk target for each index, or null, and is always the same length as paths.

        Reads host memory only: the shortcut targets were resolved once when the drag arrived, so calling this repeatedly costs no filesystem access.

      • getResolvedPaths: () => (string | null)[]

        Shortcut targets for the current drag session, parallel to dnd.getPaths.

        Windows puts the .lnk file itself in a dropped file list, which foobar2000 cannot play, so the host reads each shortcut's target and publishes it at the same index. The two arrays are always the same length, and an entry is null whenever no target is available: the path is not a shortcut, the shortcut names a shell namespace object such as the recycle bin instead of a file, the recorded target is too long to come back intact (Windows caps it at MAX_PATH, and a truncated path would name a different file), COM was unavailable, or resolution was skipped to keep the drop responsive. Never an empty string, so a truthiness test is enough.

        A target says where the shortcut points, not that the file is there: a BROKEN shortcut reports the path its .lnk recorded rather than null, because Windows hands that path back whether or not the target still exists, and the host cannot afford a filesystem check on the thread the drag blocks. Expect a non-null entry to occasionally name nothing.

        Only .lnk is resolved. .url, .library-ms and virtual search results report null.

        Synchronous snapshot read, so it carries the same timing caveat as dnd.getPaths and returns an empty array in an iframe. The resolvedPaths field of dnd.getPathsAsync and of the dnd:enter / dnd:drop payloads is the reliable equivalent.

        const paths = fb.dnd.getPaths();
        const targets = fb.dnd.getResolvedPaths();
        const playable = paths.map((p, i) => targets[i] ?? p);
      • hasFiles: () => boolean

        Whether the snapshot says the current drag carries a file list.

        Useful during dragover, where the browser withholds dataTransfer.files and exposes only items.length, leaving the page unable to tell files from other payloads. Carries the same timing caveat as dnd.getPaths; the authoritative value is the hasFiles field of the dnd:enter payload.

      • onDragEnded: (handler: (payload: DndDragEndedPayload) => void) => () => void

        Subscribes to dnd:dragEnded, which fires only when the host declines, at the moment the drag starts, to attach files to a drag-out. The drag itself goes on as an ordinary page drag without files, so a drop inside the page still works; it is cancelled only in the rare case that the host cannot remove the token text from the drag data.

        A successful hand-over produces no event; watch the element's own dragend for the outcome. The payload's code tells the page whether to mint a new token (PERMISSION_DENIED) or fix its dragstart handler (INVALID_PARAMS). OPERATION_FAILED means the file list could not be attached. A valid token is consumed before these last two checks, so request a fresh token before retrying either failure.

      • prepareDrag: (paths: string[]) => Promise<DndPrepareDragResponse>

        Exchanges a list of tracks for a one-shot token that lets the next drag out of this window carry those files.

        The token, not the paths, is what the page hands to the drag: call this BEFORE the drag begins (on pointerdown or mousedown), keep the token, and in the dragstart handler pass it synchronously to dnd.applyDragToken. Awaiting inside dragstart is too late: the drag data store is writable only while that handler runs synchronously, so a token written after an await is silently dropped and the drag goes out empty. A very fast press-and-move can also outrun this call, in which case the drag has no token yet; a page can detect that and treat the drag as an ordinary one.

        Token rules: valid for 30 seconds, spent by the first drag that uses it, bound to the window that minted it, and superseded by the next successful call from the same window (only the most recent token is live). Any other use is refused at drag start with a dnd:dragEnded of PERMISSION_DENIED, and the drag goes on as an ordinary page drag without files.

        What lands at the drop target is always a physical file. A track inside a cue sheet or a multi-track container drags the whole container (a path|subsong:N entry loses its suffix), an archive:// or unpack:// entry drags the whole archive, and several requested entries can collapse into one file; the container-internal position is not carried. Paths are validated the same way as for queue.addPaths, after being normalised to native paths. Whether the file still exists is not checked: a stale path can get a token, but an accepted drop does not guarantee that the target copied a file.

        Handler failures resolve with an error envelope rather than rejecting; transport failures can still reject. Codes: NOT_FOUND (calling window has no drag-drop registration), ORIGIN_DENIED (document origin not trusted to drag files out; checked before any path is inspected), NOT_SUPPORTED (see dragOut on dnd.getCapabilities), INVALID_PARAMS (paths missing, empty or not all strings), INVALID_PATH (an entry has no local file behind it, such as a stream or a cdda:// track; paths[i] names the offending index in the list you passed), PERMISSION_DENIED (an entry was refused by path security; here paths[i] indexes the normalised, de-duplicated list, which may be shorter than yours), OPERATION_FAILED (a token could not be created). Error messages never contain a path.

        let token = null;
        el.addEventListener('pointerdown', async () => {
        token = null;
        const r = await fb.dnd.prepareDrag([trackPath]);
        if (r.success) token = r.token;
        });
        el.addEventListener('dragstart', (e) => {
        if (token) fb.dnd.applyDragToken(e.dataTransfer, token);
        });
        el.addEventListener('dragend', (e) => {
        // 'copy' when a target took the files, 'none' otherwise.
        console.log(e.dataTransfer.dropEffect);
        });
      • startDrag: (_type?: string) => Promise<DndStartDragResponse>

        Report that programmatically starting a native drag is unsupported.

        This endpoint does not start a drag. The host handler resolves with a { success: false, code: 'NOT_SUPPORTED' } envelope rather than rejecting, because the host delivers handler-returned error envelopes as a normal result. Test success; transport failures can still reject.

        Use dnd.prepareDrag with dnd.applyDragToken instead.

    • dsp: {
          addDsp: (guid: string, position?: number) => Promise<DspAddDspResponse>;
          applyPreset: (
              indexOrName: string | number,
          ) => Promise<DspApplyPresetResponse>;
          getAvailable: () => Promise<DspGetAvailableResponse>;
          getChain: () => Promise<DspGetChainResponse>;
          getPresets: () => Promise<DspGetPresetsResponse>;
          moveDsp: (from: number, to: number) => Promise<DspMoveDspResponse>;
          removeDsp: (index: number) => Promise<DspRemoveDspResponse>;
          setChain: (
              dsps: readonly Pick<DspChainSpec, "guid">[],
          ) => Promise<DspSetChainResponse>;
      }

      dsp — DSP chain / preset namespace.

      • addDsp: (guid: string, position?: number) => Promise<DspAddDspResponse>

        Insert a processor into the active chain with its default settings.

      • applyPreset: (indexOrName: string | number) => Promise<DspApplyPresetResponse>

        Apply a preset by index (number) or name (string).

      • getAvailable: () => Promise<DspGetAvailableResponse>

        List every installed DSP processor.

      • getChain: () => Promise<DspGetChainResponse>

        Read the active DSP chain and which preset, if any, it currently corresponds to.

      • getPresets: () => Promise<DspGetPresetsResponse>

        List the DSP presets stored in the profile and which one is selected.

      • moveDsp: (from: number, to: number) => Promise<DspMoveDspResponse>

        Move one entry of the active chain to another position, keeping its settings.

      • removeDsp: (index: number) => Promise<DspRemoveDspResponse>

        Remove one entry from the active chain by index.

      • setChain: (dsps: readonly Pick<DspChainSpec, "guid">[]) => Promise<DspSetChainResponse>

        Replace the whole chain. Only guid is sent for each entry, since the host refuses any other key; the rows getChain reports can therefore be passed back as they are.

    • event: {
          emit: (
              eventName: string,
              payload?: JsonValue,
              excludeSelf?: boolean,
          ) => Promise<EventEmitResponse>;
          emitTo: (
              eventName: string,
              payload: JsonValue,
              targetWindowId: string,
          ) => Promise<EventEmitToResponse>;
      }

      event — custom event broadcast / direct delivery namespace.

      • emit: (
            eventName: string,
            payload?: JsonValue,
            excludeSelf?: boolean,
        ) => Promise<EventEmitResponse>

        Broadcast an event to every connected window (optionally excluding self). Receivers get { payload, sourceWindowId } under eventName.

      • emitTo: (
            eventName: string,
            payload: JsonValue,
            targetWindowId: string,
        ) => Promise<EventEmitToResponse>

        Deliver an event to a specific window by id. An id no open window has fails with code: 'NOT_FOUND'.

    • file: {
          cancelOp: (operationId: string) => Promise<FileCancelOpResponse>;
          copy: (
              source: string,
              destination: string,
              opts?: Omit<FileCopyParams, "source" | "destination">,
          ) => Promise<FileCopyResponse>;
          copyAsync: (
              items: FileOpEntry[],
              opts?: FileOpAsyncOptions,
          ) => Promise<FileCopyAsyncResponse>;
          delete: (
              path: string,
              opts?: Omit<FileDeleteParams, "path">,
          ) => Promise<FileDeleteResponse>;
          deleteAsync: (
              paths: string[],
              opts?: FileDeleteAsyncOptions,
          ) => Promise<FileDeleteAsyncResponse>;
          exists: (path: string) => Promise<FileExistsResponse>;
          getInfo: (path: string) => Promise<FileGetInfoResponse>;
          list: (
              path: string,
              opts?: Omit<FileListParams, "path">,
          ) => Promise<FileListResponse>;
          mkdir: (path: string) => Promise<FileMkdirResponse>;
          move: (source: string, destination: string) => Promise<FileMoveResponse>;
          moveAsync: (
              items: FileOpEntry[],
              opts?: FileOpAsyncOptions,
          ) => Promise<FileMoveAsyncResponse>;
          read: (
              path: string,
              opts?: Omit<FileReadParams, "path">,
          ) => Promise<FileReadResponse>;
          readBinary: (path: string) => Promise<Uint8Array<ArrayBufferLike>>;
          rename: (path: string, newName: string) => Promise<FileRenameResponse>;
          write: (
              path: string,
              content: string,
              opts?: Omit<FileWriteParams, "content" | "path">,
          ) => Promise<FileWriteResponse>;
          writeBinary: (
              path: string,
              bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
              opts?: FileBinaryWriteOptions,
          ) => Promise<FileWriteResponse>;
          writeDataUrl: (
              path: string,
              dataUrl: string,
              opts?: FileBinaryWriteOptions,
          ) => Promise<FileWriteResponse>;
      }

      file — file-system namespace.

      • cancelOp: (operationId: string) => Promise<FileCancelOpResponse>

        Stop an operation started by file.copyAsync, file.moveAsync or file.deleteAsync.

        Cancellation takes effect part-way through a batch rather than at the end of it. A copy or move stops within one file - the file in flight is aborted and its partial copy removed; a delete stops at the next entry. Entries already done keep their results, every remaining entry is reported as skipped / cancelled, and the run still ends with a file:opComplete carrying cancelled: true. Closing a popup cancels the operations that popup started; a panel host has no such hook, so its operations run to the end unless this method stops them.

      • copy: (
            source: string,
            destination: string,
            opts?: Omit<FileCopyParams, "source" | "destination">,
        ) => Promise<FileCopyResponse>

        Copy a file or a whole directory tree, blocking until the copy is done.

      • copyAsync: (
            items: FileOpEntry[],
            opts?: FileOpAsyncOptions,
        ) => Promise<FileCopyAsyncResponse>

        Cancellable, non-blocking batch copy. The work runs on a host worker thread, so unlike file.copy, copying a large album does not freeze the UI.

        Returns a { operationId, totalCount } receipt immediately; the outcome arrives in batches on file:opProgress, followed by one file:opComplete. Two paths skip that closing event - the host shutting down mid-run, and an unexpected host-side failure - so a listener that must not leak state should carry its own timeout rather than wait on it forever.

        Both events go to the window that made the call while that window is alive. Once it is gone the host can no longer resolve it and falls back to the main instance, so a late event may surface in a window that did not start the operation.

        One result is reported per entry, not per file: a directory entry is reported once its whole tree has been walked. Copying a directory onto an existing directory merges into it, and files already present there are skipped without being reported individually, so the entry still reports status: 'ok'. A file entry whose destination already exists is reported as skipped / already-exists unless overwrite is set.

        Path validation is all-or-nothing: if any entry fails the host's read or write check, the whole call is rejected with PERMISSION_DENIED and no operationId is produced. At most 8 operations may be in flight process-wide.

      • delete: (
            path: string,
            opts?: Omit<FileDeleteParams, "path">,
        ) => Promise<FileDeleteResponse>

        Delete a file or directory, to the Recycle Bin unless moveToTrash is false.

      • deleteAsync: (
            paths: string[],
            opts?: FileDeleteAsyncOptions,
        ) => Promise<FileDeleteAsyncResponse>

        Cancellable, non-blocking batch delete, with the same receipt-plus-events contract as file.copyAsync. Results carry no destination.

        moveToTrash: true (the default) hands each path to the shell, which requires the host's main thread, so those deletes run there in batches of 16 and yield in between. moveToTrash: false deletes on a worker thread and removes non-empty directories, which the synchronous file.delete refuses to do in that mode.

      • exists: (path: string) => Promise<FileExistsResponse>

        Check whether a path exists and whether it is a file or a directory.

      • getInfo: (path: string) => Promise<FileGetInfoResponse>

        Describe a file or directory: size, timestamps, and attributes.

      • list: (path: string, opts?: Omit<FileListParams, "path">) => Promise<FileListResponse>

        List the files and subdirectories of a directory.

      • mkdir: (path: string) => Promise<FileMkdirResponse>

        Create a directory together with any missing parents.

      • move: (source: string, destination: string) => Promise<FileMoveResponse>

        Move a file or directory, blocking until the move is done.

      • moveAsync: (
            items: FileOpEntry[],
            opts?: FileOpAsyncOptions,
        ) => Promise<FileMoveAsyncResponse>

        Cancellable, non-blocking batch move, with the same receipt-plus-events contract as file.copyAsync.

        Within one volume a move is a rename and costs nothing regardless of size. Across volumes the host falls back to copy-then-delete-source; that entry still reports status: 'ok' but carries reason: 'cross-volume' so the extra cost is visible. Unlike file.copyAsync, a directory whose destination already exists is reported as skipped / already-exists rather than merged.

        overwrite covers file destinations only. An existing directory destination is never replaced, because Windows cannot swap a directory in place: on the same volume such an entry ends as skipped or failed instead of overwriting.

      • read: (path: string, opts?: Omit<FileReadParams, "path">) => Promise<FileReadResponse>

        Read a file as text, or as Base64 with encoding: "binary".

      • readBinary: (path: string) => Promise<Uint8Array<ArrayBufferLike>>

        Read exact bytes; rejects on Host failure or malformed Base64.

      • rename: (path: string, newName: string) => Promise<FileRenameResponse>

        Rename a file or directory within its parent directory.

      • write: (
            path: string,
            content: string,
            opts?: Omit<FileWriteParams, "content" | "path">,
        ) => Promise<FileWriteResponse>

        Write text, or bytes decoded from Base64, to a file. Missing parent directories are created first.

      • writeBinary: (
            path: string,
            bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
            opts?: FileBinaryWriteOptions,
        ) => Promise<FileWriteResponse>

        Write exact bytes using the host's base64: binary wire format.

      • writeDataUrl: (
            path: string,
            dataUrl: string,
            opts?: FileBinaryWriteOptions,
        ) => Promise<FileWriteResponse>

        Write a canonical Base64 Data URL; rejects malformed input.

    • http: {
          abort: (requestId: string) => Promise<HttpAbortResponse>;
          delete: {
              (url: string, body?: JsonValue): Promise<HttpGetResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpBinaryRequestOptions,
              ): Promise<HttpBinaryResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpRequestOptions,
              ): Promise<HttpGetResponse>;
          };
          disableDefaultDownloadLogger: () => void;
          download: (
              url: string,
              saveTo: string,
              opts?: HttpDownloadOptions,
          ) => Promise<HttpDownloadResponse>;
          get: {
              (url: string): Promise<HttpGetResponse>;
              (url: string, opts: HttpBinaryRequestOptions): Promise<HttpBinaryResponse>;
              (url: string, opts: HttpRequestOptions): Promise<HttpGetResponse>;
          };
          head: (
              url: string,
              opts?: Omit<HttpRequestOptions, "responseType">,
          ) => Promise<HttpHeadResponse>;
          patch: {
              (url: string, body?: JsonValue): Promise<HttpGetResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpBinaryRequestOptions,
              ): Promise<HttpBinaryResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpRequestOptions,
              ): Promise<HttpGetResponse>;
          };
          post: {
              (url: string, body?: JsonValue): Promise<HttpGetResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpBinaryRequestOptions,
              ): Promise<HttpBinaryResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpRequestOptions,
              ): Promise<HttpGetResponse>;
          };
          put: {
              (url: string, body?: JsonValue): Promise<HttpGetResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpBinaryRequestOptions,
              ): Promise<HttpBinaryResponse>;
              (
                  url: string,
                  body: JsonValue,
                  opts: HttpRequestOptions,
              ): Promise<HttpGetResponse>;
          };
          request: {
              (url: string): Promise<HttpGetSuccess>;
              (url: string, opts: HttpBinaryRequestOptions): Promise<HttpBinarySuccess>;
              (url: string, opts: HttpRequestOptions): Promise<HttpGetSuccess>;
          };
      }

      http — HTTP requests made by the host process.

      Requests are not subject to CORS. Only http and https URLs are allowed, and local or private network addresses fail with PERMISSION_DENIED unless the host setting allows them.

      Body-bearing verbs (post / put / delete / patch) accept the body as a positional argument; the host sends a non-string body as its JSON text.

      • abort: (requestId: string) => Promise<HttpAbortResponse>

        Cancel an in-flight HTTP request or download by its requestId.

      • delete: {
            (url: string, body?: JsonValue): Promise<HttpGetResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpBinaryRequestOptions,
            ): Promise<HttpBinaryResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpRequestOptions,
            ): Promise<HttpGetResponse>;
        }

        Send a DELETE request with an optional body.

      • disableDefaultDownloadLogger: () => void

        Detach the default failure logger; see disableDefaultHttpDownloadLogger.

      • download: (
            url: string,
            saveTo: string,
            opts?: HttpDownloadOptions,
        ) => Promise<HttpDownloadResponse>

        Download a URL into a file, creating missing folders.

      • get: {
            (url: string): Promise<HttpGetResponse>;
            (url: string, opts: HttpBinaryRequestOptions): Promise<HttpBinaryResponse>;
            (url: string, opts: HttpRequestOptions): Promise<HttpGetResponse>;
        }

        Send a GET request.

      • head: (
            url: string,
            opts?: Omit<HttpRequestOptions, "responseType">,
        ) => Promise<HttpHeadResponse>

        Send a HEAD request.

      • patch: {
            (url: string, body?: JsonValue): Promise<HttpGetResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpBinaryRequestOptions,
            ): Promise<HttpBinaryResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpRequestOptions,
            ): Promise<HttpGetResponse>;
        }

        Send a PATCH request with an optional body.

      • post: {
            (url: string, body?: JsonValue): Promise<HttpGetResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpBinaryRequestOptions,
            ): Promise<HttpBinaryResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpRequestOptions,
            ): Promise<HttpGetResponse>;
        }

        Send a POST request with an optional body.

      • put: {
            (url: string, body?: JsonValue): Promise<HttpGetResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpBinaryRequestOptions,
            ): Promise<HttpBinaryResponse>;
            (
                url: string,
                body: JsonValue,
                opts: HttpRequestOptions,
            ): Promise<HttpGetResponse>;
        }

        Send a PUT request with an optional body.

      • request: {
            (url: string): Promise<HttpGetSuccess>;
            (url: string, opts: HttpBinaryRequestOptions): Promise<HttpBinarySuccess>;
            (url: string, opts: HttpRequestOptions): Promise<HttpGetSuccess>;
        }

        Event-driven GET that awaits the http:response event. The host may either respond synchronously (async: false) or queue the request and deliver the result via http:response. A client-side timeout (default 35 s, or opts.timeout + 5000 ms) guards against the event never arriving.

        Unlike the other verbs it resolves with the success branch only. A failure the host reports rejects with an Error whose message is the failure's error; a failure delivered by http:response also carries that payload as the error's response. The client timeout rejects as well, after aborting the host request.

    • Readonlyinvoke: <TResp = unknown>(method: string, params?: object) => Promise<TResp>
    • ReadonlyisAvailable: () => boolean
    • jitQueue: {
          clear: () => Promise<JitQueueClearResponse>;
          enqueueNext: (
              opts: JitQueueEnqueueNextParams,
          ) => Promise<JitQueueEnqueueNextResponse>;
          getState: () => Promise<JitQueueGetStateResponse>;
          notifyEmpty: () => Promise<JitQueueNotifyEmptyResponse>;
          playNow: (opts: JitQueuePlayNowParams) => Promise<JitQueuePlayNowResponse>;
          preloadBatch: (
              opts: JitQueuePreloadBatchParams,
          ) => Promise<JitQueuePreloadBatchResponse>;
          skip: () => Promise<JitQueueSkipResponse>;
          stop: (opts?: JitQueueStopParams) => Promise<JitQueueStopResponse>;
      }

      jitQueue — just-in-time queue namespace.

      Distinct from queue (the foobar2000 play-queue): jitQueue is the streaming pre-load queue for adaptive playback.

    • jitSession: {
          adoptNative: (
              params: JitSessionAdoptNativeParams,
          ) => Promise<JitSessionAdoptNativeResponse>;
          claimControl: (
              params: JitSessionClaimControlParams,
          ) => Promise<JitSessionClaimControlResponse>;
          create: (
              params: JitSessionCreateParams,
          ) => Promise<JitSessionCreateResponse>;
          discover: () => Promise<JitSessionDiscoverResponse>;
          getCapabilities: () => Promise<JitSessionGetCapabilitiesResponse>;
          getNativeContext: (
              params: JitSessionGetNativeContextParams,
          ) => Promise<JitSessionGetNativeContextResponse>;
          getOperation: (
              params: JitSessionGetOperationParams,
          ) => Promise<JitSessionGetOperationResponse>;
          getState: (
              params: JitSessionGetStateParams,
          ) => Promise<JitSessionGetStateResponse>;
          play: (params: JitSessionPlayParams) => Promise<JitSessionPlayResponse>;
          playNative: (
              params: JitSessionPlayNativeParams,
          ) => Promise<JitSessionPlayNativeResponse>;
          prepareAdoption: (
              params: JitSessionPrepareAdoptionParams,
          ) => Promise<JitSessionPrepareAdoptionResponse>;
          release: (
              params: JitSessionReleaseParams,
          ) => Promise<JitSessionReleaseResponse>;
          setNativeNext: (
              params: JitSessionSetNativeNextParams,
          ) => Promise<JitSessionSetNativeNextResponse>;
          setNativeQueue: (
              params: JitSessionSetNativeQueueParams,
          ) => Promise<JitSessionSetNativeQueueResponse>;
          setNext: (
              params: JitSessionSetNextParams,
          ) => Promise<JitSessionSetNextResponse>;
          skip: (params: JitSessionSkipParams) => Promise<JitSessionSkipResponse>;
          stop: (params: JitSessionStopParams) => Promise<JitSessionStopResponse>;
      }

      Control a document-owned JIT playback session; methods return host response envelopes.

    • JitSessionClient: typeof JitSessionClient
    • keyboard: {
          getRegisteredHotkeys: () => Promise<
              KeyboardGetRegisteredHotkeysResponse,
          >;
          registerHotkey: (
              key: string,
              action: string,
              opts?: Omit<KeyboardRegisterHotkeyParams, "key" | "action">,
          ) => Promise<KeyboardRegisterHotkeyResponse>;
          registerShortcut: (
              key: string,
              action: string,
          ) => Promise<KeyboardRegisterShortcutResponse>;
          setReservedKeys: (
              keys: string[],
              options?: { all?: boolean },
          ) => Promise<KeyboardSetReservedKeysResponse>;
          unregisterHotkey: (
              opts: KeyboardUnregisterHotkeyParams,
          ) => Promise<KeyboardUnregisterHotkeyResponse>;
      }

      keyboard — hotkey / shortcut registration namespace.

      • getRegisteredHotkeys: () => Promise<KeyboardGetRegisteredHotkeysResponse>

        List registered system hotkeys followed by local shortcuts. The shortcut entries go away with registerShortcut in 3.0.

      • registerHotkey: (
            key: string,
            action: string,
            opts?: Omit<KeyboardRegisterHotkeyParams, "key" | "action">,
        ) => Promise<KeyboardRegisterHotkeyResponse>

        Register a system-wide hotkey; the response carries the numeric id. The hotkey is released when this page navigates or reloads and when its window closes.

      • registerShortcut: (key: string, action: string) => Promise<KeyboardRegisterShortcutResponse>

        Store a key combination under an action name. Nothing matches key presses against it.

        Has no effect and will be removed in 3.0; listen for keydown in the page instead.

      • setReservedKeys: (
            keys: string[],
            options?: { all?: boolean },
        ) => Promise<KeyboardSetReservedKeysResponse>

        Replace this page's reserved keys: combinations that stay with the page while it has the focus, even when foobar2000 has a keyboard shortcut for them. Cleared when the page navigates or reloads; an empty array releases them all. With { all: true } every key stays with the page, for example while it records a shortcut; call again without it to keep only keys.

      • unregisterHotkey: (
            opts: KeyboardUnregisterHotkeyParams,
        ) => Promise<KeyboardUnregisterHotkeyResponse>

        Takes exactly one of the numeric id and the original key string. Removing a shortcut by key goes away with registerShortcut in 3.0.

    • library: {
          addToPlaylist: (
              paths: string[],
              playlist?: PlaylistRef,
          ) => Promise<LibraryAddToPlaylistResponse>;
          browseDirectory: (
              path: string,
              includeFiles?: boolean,
          ) => Promise<LibraryBrowseDirectoryResponse>;
          browseTree: (
              params: LibraryBrowseTreeParams,
          ) => Promise<LibraryBrowseTreeResponse>;
          enumerateDirectories: (
              options?: LibraryEnumerateDirectoriesOptions,
          ) => AsyncGenerator<
              LibraryDirectoryBatch,
              LibraryEnumerateDirectoriesSummary,
              void,
          >;
          enumerateFieldValues: (
              field: string,
              options?: LibraryEnumerateFieldValuesOptions,
          ) => Promise<LibraryGetFieldValuesResponse>;
          enumerateTracks: (
              options?: LibraryEnumerateTracksOptions,
          ) => AsyncGenerator<
              LibraryEnumerateTracksPage,
              LibraryEnumerateTracksSummary,
              void,
          >;
          enumerateTree: (
              options: LibraryEnumerateTreeOptions,
          ) => AsyncGenerator<LibraryTreeBatch, LibraryEnumerateTreeSummary, void>;
          getAlbums: (
              options?: number | LibraryGetAlbumsParams,
          ) => Promise<LibraryGetAlbumsResponse>;
          getAlbumTracks: (
              album: string,
              albumArtist: string,
              options?: Pick<LibraryGetAlbumTracksParams, "albumId">,
          ) => Promise<LibraryGetAlbumTracksResponse>;
          getAll: (
              start?: number,
              count?: number,
              opts?: Pick<LibraryGetAllParams, "useCache" | "asyncResult"> & {
                  timeout?: number;
              },
          ) => Promise<ApiFailure | LibraryPagedTracksResponse>;
          getArtistAlbums: (
              artist: string,
              limit?: number,
              options?: Omit<LibraryGetArtistAlbumsParams, "artist" | "limit">,
          ) => Promise<LibraryGetArtistAlbumsResponse>;
          getArtists: (
              limit?: number,
              options?: Omit<LibraryGetArtistsParams, "limit">,
          ) => Promise<LibraryGetArtistsResponse>;
          getArtistTracks: (
              artist: string,
              limit?: number,
          ) => Promise<LibraryGetArtistTracksResponse>;
          getByPath: (path: string) => Promise<LibraryGetByPathResponse>;
          getCacheStats: () => Promise<LibraryGetCacheStatsResponse>;
          getChanges: (
              params?: LibraryGetChangesParams,
          ) => Promise<LibraryGetChangesResponse>;
          getCount: () => Promise<LibraryGetCountResponse>;
          getFieldValues: (
              field: string,
              limit?: number,
              separator?: string,
          ) => Promise<LibraryGetFieldValuesResponse>;
          getGenres: () => Promise<LibraryGetGenresResponse>;
          getRandomTracks: (
              count?: number,
          ) => Promise<LibraryGetRandomTracksResponse>;
          getRecentlyAdded: (
              limit?: number,
              sortBy?: "added" | "modified",
          ) => Promise<LibraryGetRecentlyAddedResponse>;
          getRoots: () => Promise<LibraryGetRootsResponse>;
          getStats: () => Promise<LibraryGetStatsResponse>;
          getStatus: () => Promise<LibraryGetStatusResponse>;
          getTracks: (
              handles: string[],
              fields?: string[],
          ) => Promise<LibraryGetTracksResponse>;
          invalidateCache: () => Promise<LibraryInvalidateCacheResponse>;
          isEnabled: () => Promise<LibraryIsEnabledResponse>;
          query: (
              query: string,
              sort?: string,
              limit?: number,
              fields?: string[],
          ) => Promise<LibraryQueryResponse>;
          refresh: () => Promise<LibraryRefreshResponse>;
          rescan: () => Promise<LibraryRescanResponse>;
          search: (
              query: string,
              limit?: number,
              options?: Omit<LibrarySearchParams, "limit" | "query">,
          ) => Promise<LibrarySearchResponse>;
      }

      library — media-library namespace.

      Combines low-level invokes (search / paging / tag aggregation) with three high-level async generators that walk the library:

      • addToPlaylist: (
            paths: string[],
            playlist?: PlaylistRef,
        ) => Promise<LibraryAddToPlaylistResponse>

        Append paths to a playlist, by default the active one. Pass the playlist's guid rather than its index when the playlist list may change between choosing the target and the call, for example while a menu is open.

      • browseDirectory: (
            path: string,
            includeFiles?: boolean,
        ) => Promise<LibraryBrowseDirectoryResponse>

        Browse a directory path on disk within the media library.

      • browseTree: (params: LibraryBrowseTreeParams) => Promise<LibraryBrowseTreeResponse>

        Browse the logical library hierarchy starting from a root folder.

      • enumerateDirectories: (
            options?: LibraryEnumerateDirectoriesOptions,
        ) => AsyncGenerator<
            LibraryDirectoryBatch,
            LibraryEnumerateDirectoriesSummary,
            void,
        >

        Async generator that walks library directories breadth- or depth-first via the library.browseDirectory endpoint.

        Prefer library.enumerateTree for root-aware traversal.

      • enumerateFieldValues: (
            field: string,
            options?: LibraryEnumerateFieldValuesOptions,
        ) => Promise<LibraryGetFieldValuesResponse>

        Semantic alias for library.getFieldValues.

      • enumerateTracks: (
            options?: LibraryEnumerateTracksOptions,
        ) => AsyncGenerator<
            LibraryEnumerateTracksPage,
            LibraryEnumerateTracksSummary,
            void,
        >

        Async generator that pages through every track in the library. Honours signal for cooperative cancellation and emits a progress callback after each page fetch.

      • enumerateTree: (
            options: LibraryEnumerateTreeOptions,
        ) => AsyncGenerator<LibraryTreeBatch, LibraryEnumerateTreeSummary, void>

        Async generator that walks the typed library tree starting at a given rootId. Failed nodes are skipped (still counted) so a partial outage does not abort the traversal.

      • getAlbums: (options?: number | LibraryGetAlbumsParams) => Promise<LibraryGetAlbumsResponse>

        List albums across the library, grouped by album name plus album artist. Tracks without an album tag are skipped.

      • getAlbumTracks: (
            album: string,
            albumArtist: string,
            options?: Pick<LibraryGetAlbumTracksParams, "albumId">,
        ) => Promise<LibraryGetAlbumTracksResponse>

        Tracks of one album from getAlbums, sorted by disc number, then track number, then library order.

        Pass the row's name and albumArtist as they are. Without albumId, both are compared byte for byte, and total equals the row's trackCount. The row's artist is not the same key, and an album artist that is "" must be passed as "". A pair no row has resolves with no tracks and no row. The grouping is kept by the host until the library changes, so repeated calls do not rescan the library.

        When the row supplies albumId, pass it in options to identify the original album rather than its display names. An empty or malformed ID fails with INVALID_PARAMS; it never falls back to a name lookup.

        const page = await fb.library.getAlbums({ limit: 1 });
        const album = page.success ? page.albums[0] : undefined;
        if (album) {
        const res = await fb.library.getAlbumTracks(album.name, album.albumArtist, album);
        }
      • getAll: (
            start?: number,
            count?: number,
            opts?: Pick<LibraryGetAllParams, "useCache" | "asyncResult"> & {
                timeout?: number;
            },
        ) => Promise<ApiFailure | LibraryPagedTracksResponse>

        Fetch library tracks: count tracks from position start, sent as the host's offset and limit (host defaults 0 and 100). Resolves synchronously for paged requests and cache hits.

        Options:

        • useCache — from start 0, answer from the list the host kept after an earlier request from 0 that covered every track. Sent only when given; the host default is true. A request from 0 covering every track is kept either way.
        • asyncResult — let the host build a request from 0 that covers every track off the main thread. Defaults to true here (the host's own default is false); it takes effect only with useCache and not when the kept list answers. The host then answers { pending: true, requestId } and delivers the page as the library:getAllResult event; this wrapper listens for that event before sending the call, so an early delivery is not missed, and resolves with the page. Pass false to have the host build the page on the main thread.
        • timeout — milliseconds to wait for the event, default 60 000; 0 or less waits indefinitely.

        Either way it resolves with a LibraryPagedTracksResponse or an ApiFailure, so callers are unaffected by the threading model. A failure envelope from the call resolves as it is. A list the host failed to build and a timeout both resolve with OPERATION_FAILED; details.requestId names the request, and a timeout also carries details.timeoutMs. The returned promise rejects only when the call itself rejects. The event listener is removed in every case.

      • getArtistAlbums: (
            artist: string,
            limit?: number,
            options?: Omit<LibraryGetArtistAlbumsParams, "artist" | "limit">,
        ) => Promise<LibraryGetArtistAlbumsResponse>

        Albums an artist appears on, as rows shaped like library.getAlbums.

        artist is compared byte for byte against each atomic tag value, so a name taken from getArtists also matches tracks where it is not the first of several credited artists, and an artist differing only in case is never pulled in. Pass one artist name: on a multi-value track the joined track.artist string matches nothing, and on a single-value track it happens to equal the atomic value, so it is not a key you can rely on. Pass match: 'substring' to match on containment instead, which also returns albums by any other artist whose name contains the argument; that mode is looser about case, matching either case wherever the argument is lowercase.

        trackCount, duration and discCount count only the tracks this artist appears on, not the whole album — getAlbums returns the album-wide figures for the same row. Rendering a row here as an album card will therefore understate it. The row's tracks, when present, identify those contributing members; use them instead of display names to distinguish equal-looking rows.

        Rows are grouped by album name alone, so identically titled albums by different artists collapse into one row; tracks whose album tag is missing are grouped under (Unknown Album) rather than dropped. Both differ from getAlbums, which keys on album plus album artist and skips tracks with no album. Cover art is not inlined: pass firstTrackAbsolutePath to artwork.getForTrack, since firstTrackPath can be a file-relative:// URI that endpoint refuses.

        There is no offset: when hasMore is true the only way to see the rest is a larger limit.

      • getArtists: (
            limit?: number,
            options?: Omit<LibraryGetArtistsParams, "limit">,
        ) => Promise<LibraryGetArtistsResponse>

        List credited artists with per-artist aggregates.

        options.includeAlbums adds an albums array to every row — the (name, artist) identities of the albums that artist is credited on, so an "artist → albums" section can be built from one call instead of one getArtistAlbums scan per artist. limit caps the rows, never the albums inside them.

      • getArtistTracks: (artist: string, limit?: number) => Promise<LibraryGetArtistTracksResponse>

        Tracks an artist appears on.

        artist is matched exactly as in getArtistAlbums under match: 'exact': compared byte for byte against each atomic tag value, so a name from getArtists matches even when it is not the first of several credited artists, and an artist differing only in case is never pulled in.

      • getByPath: (path: string) => Promise<LibraryGetByPathResponse>

        Look up one file in the library and return its track metadata.

      • getCacheStats: () => Promise<LibraryGetCacheStatsResponse>

        Report diagnostic cache hit/miss statistics for library queries and indexes.

      • getChanges: (params?: LibraryGetChangesParams) => Promise<LibraryGetChangesResponse>

        Fetch the library revision and tracks changed after since for local incremental sync. Pass previous epoch and revision; when omitted or mismatched, returns resync: true with full handles. Fails with OPERATION_PENDING while the library is still loading.

      • getCount: () => Promise<LibraryGetCountResponse>

        Report the total number of tracks in the library.

      • getFieldValues: (
            field: string,
            limit?: number,
            separator?: string,
        ) => Promise<LibraryGetFieldValuesResponse>

        Report every distinct value of one metadata tag across the library with track counts.

      • getGenres: () => Promise<LibraryGetGenresResponse>

        Report every genre in the library with its track count, ordered by name.

      • getRandomTracks: (count?: number) => Promise<LibraryGetRandomTracksResponse>

        Draw tracks at random from the whole library without duplicates.

      • getRecentlyAdded: (
            limit?: number,
            sortBy?: "added" | "modified",
        ) => Promise<LibraryGetRecentlyAddedResponse>

        Report the most recently added tracks of the library.

      • getRoots: () => Promise<LibraryGetRootsResponse>

        Report the library's root folders.

      • getStats: () => Promise<LibraryGetStatsResponse>

        Report aggregate track, album, and artist counts over the whole library.

      • getStatus: () => Promise<LibraryGetStatusResponse>

        Report whether the library is enabled and how many tracks it holds.

      • getTracks: (handles: string[], fields?: string[]) => Promise<LibraryGetTracksResponse>

        Fetch library rows for up to 5000 handles in the given order. Missing handles are reported in missing. Optional fields restricts row keys, as in library.query.

      • invalidateCache: () => Promise<LibraryInvalidateCacheResponse>

        Invalidate cached library query results and directory tree indexes.

      • isEnabled: () => Promise<LibraryIsEnabledResponse>

        Report whether the foobar2000 media library is enabled.

      • query: (
            query: string,
            sort?: string,
            limit?: number,
            fields?: string[],
        ) => Promise<LibraryQueryResponse>

        Run a foobar2000 query expression with an optional Title Formatting sort expression. Sorting is applied before limit truncation and total reports the untruncated hit count.

        fields narrows the rows exactly as documented on library.search.

      • refresh: () => Promise<LibraryRefreshResponse>

        Ask foobar2000 to rescan the library folders.

      • rescan: () => Promise<LibraryRescanResponse>

        Request foobar2000 to rescan the configured library folders.

      • search: (
            query: string,
            limit?: number,
            options?: Omit<LibrarySearchParams, "limit" | "query">,
        ) => Promise<LibrarySearchResponse>

        Run a foobar2000 query expression against the media library.

        options.offset / limit page the hit list; total and hasMore report the full extent. options.fields narrows each row to the named keys of a library track row, which is why rows are typed as LibraryTrackPartial. An unknown name resolves — never rejects — with { success: false, code: 'INVALID_PARAMS' } and the names under details.unknownFields.

    • log: {
          clear: () => Promise<LogClearResponse>;
          read: (lines?: number) => Promise<LogReadResponse>;
          write: (
              message: string,
              opts?: LogWriteParams,
          ) => Promise<LogWriteResponse>;
      }

      log — log-file read/write namespace.

      • clear: () => Promise<LogClearResponse>

        Empty the component log file (webview_ui.log).

      • read: (lines?: number) => Promise<LogReadResponse>

        lines and totalLines are absent when the log file does not exist yet.

      • write: (message: string, opts?: LogWriteParams) => Promise<LogWriteResponse>

        Write a line to the component log file in the foobar2000 profile directory.

    • lyrics: {
          exists: (
              path: string,
              options?: Omit<LyricsExistsParams, "path">,
          ) => Promise<LyricsExistsResponse>;
          get: (
              path?: string,
              options?: Omit<LyricsGetParams, "path">,
          ) => Promise<LyricsGetResponse>;
          save: (
              path: string,
              lyricsText: string,
              opts?: LyricsSaveOptions,
          ) => Promise<LyricsSaveResponse>;
      }

      lyrics — lyrics fetch / save namespace.

      • exists: (
            path: string,
            options?: Omit<LyricsExistsParams, "path">,
        ) => Promise<LyricsExistsResponse>

        List which lyrics sources exist for path, including empty tags or files. A non-empty filename selects one file next to the audio file.

      • get: (
            path?: string,
            options?: Omit<LyricsGetParams, "path">,
        ) => Promise<LyricsGetResponse>

        Read a track's lyrics: embedded tags first, then sidecar files next to the audio file. Omit path for the playing track; with nothing playing the host answers NO_ACTIVE_ITEM. A non-empty filename replaces the automatic file candidates; use source: 'file' to skip embedded tags.

      • save: (
            path: string,
            lyricsText: string,
            opts?: LyricsSaveOptions,
        ) => Promise<LyricsSaveResponse>

        Save lyrics to one or more targets. The host takes target as an array; a single string is sent as a one-element array. With one target the response describes that write, with several each outcome is keyed under results. all writes the file and embedded targets. A non-empty filename selects the output file without applying format.

    • Experimentalmedia: {
          canPlay: (
              track: ContainerTrack,
              limits?: MediaVideoDecodingLimits,
          ) => Promise<MediaCanPlayResult>;
          getContainerInfo: (path: string) => Promise<MediaGetContainerInfoResponse>;
          getStreamUrl: (path: string) => Promise<MediaGetStreamUrlResponse>;
      }

      Local media access and advisory browser decoding capabilities.

      • ExperimentalcanPlay: (
            track: ContainerTrack,
            limits?: MediaVideoDecodingLimits,
        ) => Promise<MediaCanPlayResult>

        Ask the browser about a declared track without filling missing metadata. Video needs actual maximum frame rate and bitrate in the limits argument.

      • ExperimentalgetContainerInfo: (path: string) => Promise<MediaGetContainerInfoResponse>

        Read container metadata without decoding; missing fields remain unknown. The result describes the whole container, not a subsong timeline. An unrecognized file resolves successfully with recognized:false; read or parse failures use a failure envelope. Bridge transport errors may reject.

      • ExperimentalgetStreamUrl: (path: string) => Promise<MediaGetStreamUrlResponse>

        Issue a local media URL usable only by the requesting document. Navigation, file changes and token eviction invalidate the URL; do not persist it. Requires a trusted HTTP(S) page and a host with WebView2 media routing support. Set an element's crossOrigin to 'anonymous' before assigning src. For fetch, files larger than 2 MiB require Range; each response contains at most 2 MiB. Resolves with a success or failure envelope; bridge transport errors may reject.

    • MediaElementFollower: typeof MediaElementFollower
    • menu - main menu, context menu, and self-drawn popup menu namespace.

      • close: (reason?: string) => Promise<MenuCloseResponse>

        Close the active self-drawn popup menu, if any.

      • getContextMenu: (opts?: MenuGetContextMenuParams) => Promise<MenuGetContextMenuResponse>

        mode is one of 'auto' | 'selection' | 'playlist' | 'nowPlaying' | 'handles'.

        Prefer 'selection', 'playlist' or 'nowPlaying' whenever the target is reachable from the host playlist: those resolve handles inside the host and validate no paths. 'handles' validates every supplied path individually, which costs filesystem metadata calls per entry and is noticeably slower for network shares.

        A command leaf's source is contextmenu_dynamic when it carries subGuid, otherwise contextmenu_static.

      • getMainMenu: (
            root?: string,
            opts?: Omit<MenuGetMainMenuParams, "root">,
        ) => Promise<MenuGetMainMenuResponse>

        root scopes the returned menu tree (e.g. 'View'). opts.locale selects the displayLabel translation locale; the default 'auto' keeps the host's native labels untranslated. opts.i18n: false disables label translation entirely. opts.withAvailability (default true) includes per-submenu command availability counters.

        Leaf source follows the provider's node kind. Dynamic leaves without a usable subGuid remain dynamic and are not executable. Addressability is independent of enabled; addressCandidates is diagnostic only. Every leaf of the v1 HMENU tier reports hmenu_fallback. The flat fallback (fallback: true) keeps flags and has no commandId; see MenuCommand.

      • popup: (
            items: MenuPopupItem[],
            position?: MenuPopupPosition,
            opts?: MenuPopupOptions,
        ) => Promise<string | null>

        Show a self-drawn popup menu and await the user's choice. Resolves with the selected item id, or null when the menu is dismissed (outside click, Escape, or any other close reason). Events are matched by the menu id returned from menu.show, so overlapping callers never cross-resolve. The listeners are attached before menu.show is sent, so a result that reaches the page ahead of the call's response still settles the promise.

        opts is the same per-call presentation config as show; windowModel: 'contentSized' is the recommended model for a context menu. Rich controls report through menu:valueChanged without closing the menu, so this promise stays pending until an ordinary row is chosen or the menu is dismissed — subscribe to that event separately to track value changes.

        document.addEventListener('contextmenu', async (e) => {
        e.preventDefault();
        const id = await fb.menu.popup(items, undefined, {
        windowModel: 'contentSized',
        backdrop: 'acrylic',
        });
        if (id) console.log('selected', id);
        });
      • runContextCommand: (
            command: string,
            opts?: Omit<MenuRunContextCommandParams, "command">,
        ) => Promise<MenuRunContextCommandResponse>

        Runs a context-menu command against the now-playing track, falling back to the active playlist selection.

        command accepts a GUID or a command name. opts.subGuid addresses a dynamically generated child (a rating value, a converter preset); without it the owning container is targeted instead, which is a silent no-op.

        executionConfirmed distinguishes "the host reported the command ran" from "the command was dispatched through an entry point that returns nothing". It is absent on the early-validation failures.

      • runContextCommandById: (
            id: number,
            opts?: Omit<MenuRunContextCommandByIdParams, "id">,
        ) => Promise<MenuRunContextCommandByIdResponse>

        Runs the context-menu node whose commandId getContextMenu reported. The host rebuilds the menu from opts.mode and opts.handles, so pass the values that call used; an id the rebuilt menu lacks fails with code: 'NOT_FOUND'.

        An id is a position, so a changed menu or selection can make it run another item. Pass the node's path as opts.expectPath and the menu's targetKey as opts.expectTarget to have the host refuse instead; the refusal carries details.reason and runs nothing, so reopen the menu.

      • runMainMenuCommand: (
            command: string,
            opts?: Omit<MenuRunMainMenuCommandParams, "command">,
        ) => Promise<MenuRunMainMenuCommandResponse>

        Runs a main menu command.

        command accepts a GUID ('{11213A01-...}'), a leaf name, or a slash-separated path. Prefer the GUID: it is the only form that is stable across hosts, because a localized build reports localized labels.

        opts.subGuid addresses a dynamic child command, paired with its owning command GUID. A path must match every ancestor; a wrong prefix never falls back to the leaf name. Root-filtered results keep their full paths.

        Business failures resolve as success: false with a code: MENU_ITEM_DISABLED (command exists but is greyed out), MENU_MATCH_AMBIGUOUS (identity is ambiguous; see details.candidates), MENU_COMMAND_NOT_FOUND (no command has that name or path), NOT_FOUND (no command owns that GUID), or OPERATION_FAILED (state cannot be read or the provider fails). Dynamic containers cannot be executed.

      • show: (
            items: MenuPopupItem[],
            position?: MenuPopupPosition,
            opts?: MenuPopupOptions,
        ) => Promise<MenuShowResponse>

        Show a self-drawn (WebView-rendered) popup menu at position (defaults to the cursor). Resolves with the new menu id; the user's choice arrives asynchronously via the menu:select / menu:dismiss events, and a rich control's value change via menu:valueChanged (which leaves the menu open). Prefer popup when you only need the chosen item id.

        opts configures presentation per call. For a context menu prefer windowModel: 'contentSized', which draws each panel in a compact window carrying the real DWM MenuPopupOptions.backdrop material and the system shadow; opts.css restyles the menu (and with cssReplace: true takes the look over entirely).

        const { menuId } = await fb.menu.show(items, { x: e.screenX, y: e.screenY }, {
        windowModel: 'contentSized',
        backdrop: 'acrylic',
        css: '.fb-menu { background: rgba(32, 32, 32, 0.82); }',
        });
      • showNativePopup: (opts?: MenuShowNativePopupParams) => Promise<MenuShowNativePopupResponse>

        Defaults to auto: handles, now playing, playlist selection, then playlist context.

        The same cost note as getContextMenu applies — prefer mode: 'selection' over supplying handles for playlist rows.

    • metadata: {
          cancelProbe: (
              operationId: string,
          ) => Promise<MetadataCancelProbeResponse>;
          disableDefaultLogger: () => void;
          embedArtwork: (
              path: string,
              opts: Omit<MetadataEmbedArtworkParams, "path" | "target"> & {
                  target?: string | string[];
              },
          ) => Promise<MetadataEmbedArtworkResponse>;
          embedArtworkBytes: (
              path: string,
              bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
              opts?: MetadataArtworkBytesOptions,
          ) => Promise<MetadataEmbedArtworkResponse>;
          embedArtworkFromDataUrl: (
              path: string,
              dataUrl: string,
              opts?: MetadataArtworkBytesOptions,
          ) => Promise<MetadataEmbedArtworkResponse>;
          probeBatchAsync: (
              paths: string[],
              opts?: Omit<MetadataProbeBatchAsyncParams, "paths">,
          ) => Promise<MetadataProbeBatchAsyncResponse>;
          read: (
              path: string,
              opts?: Omit<MetadataReadParams, "path">,
          ) => Promise<MetadataReadResponse>;
          readBatch: (paths: string[]) => Promise<MetadataReadBatchResponse>;
          readByPath: (
              path: string,
              opts?: Omit<MetadataReadByPathParams, "path">,
          ) => Promise<MetadataReadByPathResponse>;
          readRaw: (
              path: string,
              opts?: Omit<MetadataReadRawParams, "path">,
          ) => Promise<MetadataReadRawResponse>;
          removeEmbeddedArt: (
              path: string,
              opts?: Omit<MetadataRemoveEmbeddedArtParams, "path">,
          ) => Promise<MetadataRemoveEmbeddedArtResponse>;
          removeField: (
              path: string,
              field: string,
              opts?: Omit<MetadataRemoveFieldParams, "path" | "tags">,
          ) => Promise<MetadataRemoveFieldResponse>;
          removeTag: (
              path: string,
              tags: string[],
              opts?: Omit<MetadataRemoveTagParams, "path" | "tags">,
          ) => Promise<MetadataRemoveTagResponse>;
          write: (
              path: string,
              tags: JsonObject,
              opts?: Omit<MetadataWriteParams, "path" | "tags">,
          ) => Promise<MetadataWriteResponse>;
          writeBatch: (
              items: MetadataWriteBatchItem[],
          ) => Promise<MetadataWriteBatchResponse>;
      }

      metadata — tag read / write namespace.

      • cancelProbe: (operationId: string) => Promise<MetadataCancelProbeResponse>

        Stop a probe started by metadata.probeBatchAsync.

        Cancellation interrupts the in-progress disk read rather than waiting for it, and the run always finishes with a metadata:probeComplete carrying cancelled: true. Paths not yet reached are never reported, and the interrupted path is reported as neither success nor failure.

      • disableDefaultLogger: () => void

        Detach the default failure logger; see disableDefaultMetadataLogger.

      • embedArtwork: (
            path: string,
            opts: Omit<MetadataEmbedArtworkParams, "path" | "target"> & {
                target?: string | string[];
            },
        ) => Promise<MetadataEmbedArtworkResponse>

        Write artwork into the audio file or alongside it.

        opts.imageData is the image as raw Base64.

        opts.target selects the destination. The host takes an array; a single string is sent as a one-element array:

        • "embedded" (default) — write into the file's tag container via album_art_editor. Fails for formats the SDK cannot edit (e.g. CUE).
        • "file" — write a sibling image file in the audio's directory using fb2k's external artwork naming (cover.<ext> / back.<ext> / ...). The extension is inferred from the image's magic bytes.
        • "all" or ["embedded", "file"] — run both targets and return a results map; the call succeeds when either target succeeded.

        opts.filename overrides the auto-generated sidecar name (file mode only). It must be a plain file name: path separators are rejected, and so is a name made only of periods (., ..). Periods inside a name (cover..jpg) are fine.

        CUE / subsong paths share one sidecar per directory — this matches fb2k's per-directory external artwork lookup.

      • embedArtworkBytes: (
            path: string,
            bytes: ArrayBuffer | Uint8Array<ArrayBufferLike>,
            opts?: MetadataArtworkBytesOptions,
        ) => Promise<MetadataEmbedArtworkResponse>

        Embed exact image bytes without exposing the raw Base64 wire format.

      • embedArtworkFromDataUrl: (
            path: string,
            dataUrl: string,
            opts?: MetadataArtworkBytesOptions,
        ) => Promise<MetadataEmbedArtworkResponse>

        Embed a Base64 data:image/* URL; rejects malformed input.

      • probeBatchAsync: (
            paths: string[],
            opts?: Omit<MetadataProbeBatchAsyncParams, "paths">,
        ) => Promise<MetadataProbeBatchAsyncResponse>

        Cancellable, non-blocking batch probe. Reads happen on a host worker thread, so unlike readBatch, a few hundred paths do not stall the UI.

        Returns a { operationId, totalCount } receipt immediately; the results arrive in batches on metadata:probeProgress and are followed by exactly one metadata:probeComplete. Each result reports where its info came from (infoSource: 'cached' | 'direct') and, on failure, which of 'not-found' / 'unsupported-format' / 'read-error' applies - the distinction readBatch collapses into one generic error string.

        Paths may carry a |subsong:N suffix and are resolved independently; they are echoed back verbatim so they work as lookup keys. Unlike metadata.read, the batch surface does not honour the legacy #N subsong spelling, which would mis-split an extensionless filename that happens to end in #<digits>.

        Path validation is all-or-nothing: if any path fails the host's media read check the whole call is rejected with PERMISSION_DENIED and no operationId is produced. Per-path rejection is not available.

      • read: (
            path: string,
            opts?: Omit<MetadataReadParams, "path">,
        ) => Promise<MetadataReadResponse>

        Read structured metadata for a single track.

        Returns { success, path, tags, info }. tags preserves upstream key casing and may hold a single string or a string[] per multi-value field.

        For a track inside a container (CUE sheet, ISO image, multi-track file), either append |subsong:N to path or pass opts.cueIndex; the option wins when both are given. CUE track numbering starts at 1.

      • readBatch: (paths: string[]) => Promise<MetadataReadBatchResponse>

        Batch variant; returns a results[] array with one envelope entry per requested path. Each path is resolved independently and may carry its own |subsong:N suffix; there is no batch-wide subsong option.

      • readByPath: (
            path: string,
            opts?: Omit<MetadataReadByPathParams, "path">,
        ) => Promise<MetadataReadByPathResponse>

        Flat-form single-track read — every tag and technical-info field becomes a top-level field, upper-cased by the host, alongside success / path. The return shape is intentionally loose because the host forwards whatever tags the file happens to carry. canonicalPath appears only on the file-open failure envelope.

        Container tracks are addressed the same way as read().

      • readRaw: (
            path: string,
            opts?: Omit<MetadataReadRawParams, "path">,
        ) => Promise<MetadataReadRawResponse>

        Read structured metadata straight from the file, bypassing the host's metadb cache; the result carries source: 'file'.

      • removeEmbeddedArt: (
            path: string,
            opts?: Omit<MetadataRemoveEmbeddedArtParams, "path">,
        ) => Promise<MetadataRemoveEmbeddedArtResponse>

        Remove embedded artwork: one type, or every picture when type is omitted or removeAll is set.

      • removeField: (
            path: string,
            field: string,
            opts?: Omit<MetadataRemoveFieldParams, "path" | "tags">,
        ) => Promise<MetadataRemoveFieldResponse>

        Remove a single tag field.

      • removeTag: (
            path: string,
            tags: string[],
            opts?: Omit<MetadataRemoveTagParams, "path" | "tags">,
        ) => Promise<MetadataRemoveTagResponse>

        Remove one or more tag fields from a file.

      • write: (
            path: string,
            tags: JsonObject,
            opts?: Omit<MetadataWriteParams, "path" | "tags">,
        ) => Promise<MetadataWriteResponse>

        Queue tag updates and signal completion via metadata:writeComplete. The returned receipt describes the dispatch; the final outcome is on the event payload.

        String arrays replace all values of a tag; an empty array removes it. Non-string, empty or NUL-containing array elements fail the entire track with INVALID_PARAMS before any of its tags are queued.

      • writeBatch: (items: MetadataWriteBatchItem[]) => Promise<MetadataWriteBatchResponse>

        Queue one write per entry. When any entry fails (for example one without tags or with an invalid tag array), the call resolves as a failure envelope that still carries successCount, failCount and errors; the other entries were dispatched all the same.

    • misc: {
          exit: () => Promise<MiscExitResponse>;
          getComponentPath: () => Promise<MiscGetComponentPathResponse>;
          getFoobarPath: () => Promise<MiscGetFoobarPathResponse>;
          getProfilePath: () => Promise<MiscGetProfilePathResponse>;
          restart: () => Promise<MiscRestartResponse>;
          showConsole: () => Promise<MiscShowConsoleResponse>;
          showLibrarySearch: (
              query?: string,
          ) => Promise<MiscShowLibrarySearchResponse>;
          showPopupMessage: (
              message: string,
              title?: string,
          ) => Promise<MiscShowPopupMessageResponse>;
          showPreferences: () => Promise<MiscShowPreferencesResponse>;
      }

      misc — miscellaneous host actions (exit, paths, popups).

    • notification: {
          hide: () => Promise<UiHideNotificationResponse>;
          show: (
              opts: UiShowNotificationParams,
          ) => Promise<UiShowNotificationResponse>;
          showCustomMenu: (
              opts: UiShowCustomMenuParams,
          ) => Promise<UiShowCustomMenuResponse>;
          showToast: (opts: UiShowToastParams) => Promise<UiShowToastResponse>;
      }

      notification — toast / custom-menu / notification host bindings.

      Wraps the ui.* notification family so consumers do not have to remember the cross-namespace invoke('ui.showNotification', ...) spelling.

    • Readonlyoff: (event: string, handler: RawEventHandler) => void
    • Readonlyon: {
          <K extends FBEventName>(
              event: K,
              handler: FBEventHandler<K>,
          ): () => void;
          (event: string, handler: RawEventHandler): () => void;
      }
    • Readonlyonce: {
          <K extends FBEventName>(
              event: K,
              handler: FBEventHandler<K>,
          ): () => void;
          (event: string, handler: RawEventHandler): () => void;
      }
    • output: {
          getDevices: () => Promise<OutputGetDevicesResponse>;
          getEntries: () => Promise<OutputGetEntriesResponse>;
          getSettings: () => Promise<OutputGetSettingsResponse>;
      }

      output — audio-output device discovery namespace.

      • getDevices: () => Promise<OutputGetDevicesResponse>

        The available output devices, in devices.

      • getEntries: () => Promise<OutputGetEntriesResponse>

        List the output modules (foobar2000's output entries) with their capability flags.

      • getSettings: () => Promise<OutputGetSettingsResponse>

        Report the display names of the output modules.

    • panel: {
          getConfig: () => Promise<PanelGetConfigResponse>;
          setConfig: (opts: PanelSetConfigParams) => Promise<PanelSetConfigResponse>;
      }

      panel — webview panel-level config namespace.

    • PlaybackClock: typeof PlaybackClock
    • playcount: {
          get: (path: string) => Promise<PlaycountGetResponse>;
          getBatch: (paths: string[]) => Promise<PlaycountGetBatchResponse>;
          getStats: () => Promise<PlaycountGetStatsResponse>;
          set: (path: string, count: number) => Promise<PlaycountSetResponse>;
      }

      playcount — play-count read/write namespace.

      get(path) is a convenience wrapper around the batch variant.

      • get: (path: string) => Promise<PlaycountGetResponse>

        The playcount entry of one track: playcount.get with paths: [path], so the entry is results[0].

      • getBatch: (paths: string[]) => Promise<PlaycountGetBatchResponse>

        Batch fetch playcount entries for multiple tracks. Returns the full envelope so callers can inspect the aggregate count field as well as per-track success flags inside results.

      • getStats: () => Promise<PlaycountGetStatsResponse>

        Aggregate library-wide playcount statistics.

      • set: (path: string, count: number) => Promise<PlaycountSetResponse>

        foo_playcount does not currently expose a public API for mutating playback statistics. The C++ handler is a placeholder that always fails with code: 'NOT_SUPPORTED'. The count argument is retained for signature compatibility but is not sent to the host (the handler never reads it). Use fb.rating.set for rating mutation, or trigger play counts via actual playback.

    • player: {
          getCurrentTrack: () => Promise<PlaybackGetCurrentTrackResponse>;
          getCurrentTrackIndex: (
              includeTrackInfo?: boolean,
          ) => Promise<PlaybackGetCurrentTrackIndexResponse>;
          getOrder: () => Promise<PlaybackGetPlaybackOrderResponse>;
          getPlayingPlaylist: () => Promise<PlaybackGetPlayingPlaylistResponse>;
          getPosition: () => Promise<PlaybackGetPositionResponse>;
          getState: () => Promise<PlaybackGetStateResponse>;
          getStopAfterCurrent: () => Promise<PlaybackGetStopAfterCurrentResponse>;
          getVolume: () => Promise<PlaybackGetVolumeResponse>;
          mute: (muted?: boolean) => Promise<PlaybackMuteResponse>;
          next: () => Promise<PlaybackNextResponse>;
          pause: () => Promise<PlaybackPauseResponse>;
          play: () => Promise<PlaybackPlayResponse>;
          playPath: (path: string) => Promise<PlaybackPlayPathResponse>;
          playPaths: {
              (
                  paths: string[],
                  startIndex?: number,
              ): Promise<PlaybackPlayPathsResponse>;
              (
                  paths: string[],
                  opts: { replace?: boolean; startIndex?: number },
              ): Promise<PlaybackPlayPathsResponse>;
          };
          playPause: () => Promise<PlaybackPlayPauseResponse>;
          prev: () => Promise<PlaybackPreviousResponse>;
          random: () => Promise<PlaybackRandomResponse>;
          seek: (seconds: number) => Promise<PlaybackSetPositionResponse>;
          setOrder: (
              order: number | PlaybackOrder,
          ) => Promise<PlaybackSetPlaybackOrderResponse>;
          setStopAfterCurrent: (
              enabled: boolean,
          ) => Promise<PlaybackSetStopAfterCurrentResponse>;
          setVolume: (volume: number) => Promise<PlaybackSetVolumeResponse>;
          stop: () => Promise<PlaybackStopResponse>;
          toggle: () => Promise<PlaybackPlayOrPauseResponse>;
          toggleMute: () => Promise<PlaybackToggleMuteResponse>;
          toggleStopAfterCurrent: () => Promise<
              PlaybackToggleStopAfterCurrentResponse,
          >;
          volumeDown: () => Promise<PlaybackVolumeDownResponse>;
          volumeUp: () => Promise<PlaybackVolumeUpResponse>;
      }

      player — playback control namespace.

      • getCurrentTrack: () => Promise<PlaybackGetCurrentTrackResponse>

        Resolves with found and, when a track is loaded, the shared track row. The host never answers null.

      • getCurrentTrackIndex: (includeTrackInfo?: boolean) => Promise<PlaybackGetCurrentTrackIndexResponse>

        Locate the playing track in its playlist.

      • getOrder: () => Promise<PlaybackGetPlaybackOrderResponse>

        Report the active playback order as its index and its name.

      • getPlayingPlaylist: () => Promise<PlaybackGetPlayingPlaylistResponse>

        Report the playlist playback was last started from.

      • getPosition: () => Promise<PlaybackGetPositionResponse>

        Report the playback position together with the length and identity of the track. All values are zero or empty when nothing is playing.

      • getState: () => Promise<PlaybackGetStateResponse>

        Report the transport state and what the current track allows.

      • getStopAfterCurrent: () => Promise<PlaybackGetStopAfterCurrentResponse>

        Report whether playback stops after the current track.

      • getVolume: () => Promise<PlaybackGetVolumeResponse>

        Report the output volume on both scales the host uses, and whether it is muted.

      • mute: (muted?: boolean) => Promise<PlaybackMuteResponse>

        Mute by default; pass false to unmute.

      • next: () => Promise<PlaybackNextResponse>

        Skip to the next track under the current playback order.

      • pause: () => Promise<PlaybackPauseResponse>

        Pause playback. Does nothing when stopped.

      • play: () => Promise<PlaybackPlayResponse>

        Start playback, or resume when paused.

      • playPath: (path: string) => Promise<PlaybackPlayPathResponse>

        Append one file to the active playlist and play it; creates a playlist when none exists. A |subsong:N suffix selects a subsong of the file.

      • playPaths: {
            (
                paths: string[],
                startIndex?: number,
            ): Promise<PlaybackPlayPathsResponse>;
            (
                paths: string[],
                opts: { replace?: boolean; startIndex?: number },
            ): Promise<PlaybackPlayPathsResponse>;
        }

        Begin playback of the supplied paths.

        Accepts either a single numeric startIndex matching the original (paths, startIndex) signature or an options object { startIndex?, replace? } that additionally controls whether the active playlist is cleared before insertion.

        Absolute file paths. Each entry may carry a |subsong:N suffix for CUE tracks.

        Numeric startIndex (0-based offset into the active playlist), or an options object: - startIndex selects the entry to start playback from (0-based); - replace: true clears the active playlist before inserting; false (default) appends.

      • playPause: () => Promise<PlaybackPlayPauseResponse>

        Toggle between playing and paused; starts playback when stopped.

      • prev: () => Promise<PlaybackPreviousResponse>

        Skip to the previous track under the current playback order.

      • random: () => Promise<PlaybackRandomResponse>

        Start a random track of the active playlist.

      • seek: (seconds: number) => Promise<PlaybackSetPositionResponse>

        Seek within the current track. The host clamps the position to the track and reports both the requested and the applied value.

      • setOrder: (order: number | PlaybackOrder) => Promise<PlaybackSetPlaybackOrderResponse>

        Set the active playback order by index or by name; the host reports what took effect.

      • setStopAfterCurrent: (enabled: boolean) => Promise<PlaybackSetStopAfterCurrentResponse>

        Arm or disarm stopping after the current track.

      • setVolume: (volume: number) => Promise<PlaybackSetVolumeResponse>

        Set the output volume as a percentage; values outside 0 to 100 are clamped. 0 mutes.

      • stop: () => Promise<PlaybackStopResponse>

        Stop playback.

      • toggle: () => Promise<PlaybackPlayOrPauseResponse>

        Toggle between playing and paused; starts playback when stopped.

      • toggleMute: () => Promise<PlaybackToggleMuteResponse>

        Flip the mute state and report the new one.

      • toggleStopAfterCurrent: () => Promise<PlaybackToggleStopAfterCurrentResponse>

        Flip the stop-after-current flag and report the new value.

      • volumeDown: () => Promise<PlaybackVolumeDownResponse>

        Lower the volume by one step (1 dB).

      • volumeUp: () => Promise<PlaybackVolumeUpResponse>

        Raise the volume by one step (1 dB).

    • playlist: {
          add: (
              playlist: PlaylistRef,
              paths: string[],
          ) => Promise<PlaylistAddPathsResponse>;
          addAsync: (
              playlist: PlaylistRef,
              paths: string[],
          ) => Promise<PlaylistAddPathsAsyncResponse>;
          addHandles: (
              playlist: PlaylistRef,
              handles: PlaylistHandleRef[],
          ) => Promise<PlaylistAddHandlesResponse>;
          addSequential: (
              playlist: PlaylistRef,
              paths: string[],
          ) => Promise<PlaylistAddPathsSequentialResponse>;
          clear: (playlist: PlaylistRef) => Promise<PlaylistClearResponse>;
          convertToAutoplaylist: (
              playlist: PlaylistRef,
              query: string,
              sort?: string,
              keepSorted?: boolean,
          ) => Promise<PlaylistConvertToAutoplaylistResponse>;
          create: (
              name: string,
              options?: Omit<PlaylistCreateParams, "name">,
          ) => Promise<PlaylistCreateResponse>;
          createAutoplaylist: (
              name: string,
              query: string,
              sort?: string,
              keepSorted?: boolean,
          ) => Promise<PlaylistCreateAutoplaylistResponse>;
          createManagedAutoplaylist: (
              name: string,
              query: string,
              sort?: string,
              keepSorted?: boolean,
          ) => Promise<PlaylistCreateManagedAutoplaylistResponse>;
          deselectAll: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistDeselectAllResponse>;
          duplicate: (
              playlist: PlaylistRef,
              name?: string,
          ) => Promise<PlaylistDuplicateResponse>;
          focusTrack: (
              playlist: PlaylistRef,
              trackIndex: number,
          ) => Promise<PlaylistFocusTrackResponse>;
          getActive: () => Promise<PlaylistGetActiveResponse>;
          getAll: () => Promise<PlaylistGetAllResponse>;
          getAutoplaylistConfig: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetAutoplaylistConfigResponse>;
          getAutoplaylistInfo: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetAutoplaylistInfoResponse>;
          getAutoplaylistQuery: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetAutoplaylistQueryResponse>;
          getAvailableColumns: () => Promise<PlaylistGetAvailableColumnsResponse>;
          getCount: (playlist: PlaylistRef) => Promise<PlaylistGetTrackCountResponse>;
          getFocused: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetFocusedTrackResponse>;
          getFocusTrack: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetFocusTrackResponse>;
          getGroupRuns: (
              patterns: string[],
              playlist?: PlaylistRef,
          ) => Promise<PlaylistGetGroupRunsResponse>;
          getLockInfo: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetLockInfoResponse>;
          getMatchingRows: (
              query: string,
              playlist?: PlaylistRef,
          ) => Promise<PlaylistGetMatchingRowsResponse>;
          getPlaying: () => Promise<PlaylistGetPlayingResponse>;
          getPlaylistCount: () => Promise<PlaylistGetCountResponse>;
          getSelectedTracks: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetSelectedTracksResponse>;
          getSelection: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistGetSelectionResponse>;
          getTracks: (
              playlist: PlaylistRef,
              start?: number,
              count?: number,
              formats?: Record<string, string>,
              fields?: string[],
          ) => Promise<PlaylistGetTracksResponse>;
          getTracksAt: (
              playlist: PlaylistRef,
              rows: readonly number[],
              formats?: Record<string, string>,
              fields?: string[],
          ) => Promise<PlaylistGetTracksAtResponse>;
          getTracksPage: (
              playlist: PlaylistRef,
              start?: number,
              count?: number,
              formats?: Record<string, string>,
              fields?: string[],
          ) => Promise<PlaylistGetTracksResponse>;
          insertTracks: (
              playlist: PlaylistRef,
              insertIndex: number,
              handles: PlaylistHandleRef[],
              expectedVersion?: string,
          ) => Promise<PlaylistInsertTracksResponse>;
          isAutoplaylist: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistIsAutoplaylistResponse>;
          isLocked: (playlist: PlaylistRef) => Promise<PlaylistIsLockedResponse>;
          moveTracks: (
              playlist: PlaylistRef,
              indices: number[],
              delta: number,
              expectedVersion?: string,
          ) => Promise<PlaylistMoveTracksResponse>;
          onAutoplaylistConfigChanged: (
              callback: (event: PlaylistAutoplaylistConfigChangedPayload) => void,
          ) => () => void;
          onAutoplaylistUIResult: (
              callback: (event: PlaylistAutoplaylistUIResultPayload) => void,
          ) => () => void;
          playTrack: (
              playlist: PlaylistRef,
              trackIndex: number,
              options?: Omit<
                  PlaylistPlayTrackParams,
                  "index"
                  | "playlist"
                  | "playlistGuid",
              >,
          ) => Promise<PlaylistPlayTrackResponse>;
          redo: (playlist: PlaylistRef) => Promise<PlaylistRedoResponse>;
          remove: (playlist: PlaylistRef) => Promise<PlaylistRemoveResponse>;
          removeAutoplaylist: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistRemoveAutoplaylistResponse>;
          removeSelectedTracks: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistRemoveSelectedTracksResponse>;
          removeTracks: (
              playlist: PlaylistRef,
              indices: number[],
              expectedVersion?: string,
          ) => Promise<PlaylistRemoveTracksResponse>;
          rename: (
              playlist: PlaylistRef,
              name: string,
          ) => Promise<PlaylistRenameResponse>;
          reorder: (
              playlist: PlaylistRef,
              order: number[],
              expectedVersion?: string,
          ) => Promise<PlaylistReorderResponse>;
          reorderPlaylists: (
              order: readonly string[] | readonly number[],
          ) => Promise<PlaylistReorderPlaylistsResponse>;
          replaceAllAndPlay: (
              options: PlaylistReplaceAllAndPlayParams,
          ) => Promise<PlaylistReplaceAllAndPlayResponse>;
          reverse: (playlist: PlaylistRef) => Promise<PlaylistReverseResponse>;
          selectAll: (playlist: PlaylistRef) => Promise<PlaylistSelectAllResponse>;
          setActive: (playlist: PlaylistRef) => Promise<PlaylistSetActiveResponse>;
          setAutoplaylistConfig: (
              playlist: PlaylistRef,
              options: Omit<
                  PlaylistSetAutoplaylistConfigParams,
                  "playlist"
                  | "playlistGuid",
              >,
          ) => Promise<PlaylistSetAutoplaylistConfigResponse>;
          setFocused: (
              playlist: PlaylistRef,
              trackIndex: number,
              expectedVersion?: string,
          ) => Promise<PlaylistSetFocusedTrackResponse>;
          setSelection: (
              playlist: PlaylistRef,
              indices: number[],
              clearOthers?: boolean,
              expectedVersion?: string,
          ) => Promise<PlaylistSetSelectionResponse>;
          showAutoplaylistUI: (
              playlist: PlaylistRef,
          ) => Promise<PlaylistShowAutoplaylistUIResponse>;
          shuffle: (playlist: PlaylistRef) => Promise<PlaylistShuffleResponse>;
          sort: (
              playlist: PlaylistRef,
              pattern: string,
              descending?: boolean,
              selectedOnly?: boolean,
          ) => Promise<PlaylistSortResponse>;
          undo: (playlist: PlaylistRef) => Promise<PlaylistUndoResponse>;
      }

      playlist — playlist management namespace.

      Methods that take a playlist accept a PlaylistRef: its index, or the guid from getAll, which still names the same playlist after others are added, removed or reordered.

      • add: (playlist: PlaylistRef, paths: string[]) => Promise<PlaylistAddPathsResponse>

        Append files, folders or URLs. foobar2000 resolves the batch as its own Add Files does, so the rows do not keep the given order; use playlist.addSequential for that. Entries over 2048 characters and entries that resolve to nothing are counted in invalidCount; when nothing is added the call fails with NOT_FOUND.

      • addAsync: (
            playlist: PlaylistRef,
            paths: string[],
        ) => Promise<PlaylistAddPathsAsyncResponse>

        Start adding paths without waiting; playlist:addComplete with the returned operationId reports the outcome. Empty entries and entries over 2048 characters are counted in invalidCount.

      • addHandles: (
            playlist: PlaylistRef,
            handles: PlaylistHandleRef[],
        ) => Promise<PlaylistAddHandlesResponse>

        Append tracks by path or { path, subsong }. Unusable entries are counted in invalidCount; when none is usable the call fails with NOT_FOUND.

      • addSequential: (
            playlist: PlaylistRef,
            paths: string[],
        ) => Promise<PlaylistAddPathsSequentialResponse>

        Append paths in the given order and report the row of each added track. Entries over 2048 characters and entries that resolve to nothing are skipped.

      • clear: (playlist: PlaylistRef) => Promise<PlaylistClearResponse>

        Remove every track from a playlist, saving an undo point first.

      • convertToAutoplaylist: (
            playlist: PlaylistRef,
            query: string,
            sort?: string,
            keepSorted?: boolean,
        ) => Promise<PlaylistConvertToAutoplaylistResponse>

        Turn an existing playlist into an autoplaylist; its tracks are replaced by the query results.

      • create: (
            name: string,
            options?: Omit<PlaylistCreateParams, "name">,
        ) => Promise<PlaylistCreateResponse>

        Create an empty playlist with the given name and options.

      • createAutoplaylist: (
            name: string,
            query: string,
            sort?: string,
            keepSorted?: boolean,
        ) => Promise<PlaylistCreateAutoplaylistResponse>

        Create a playlist that foobar2000 fills from a library query and keeps up to date.

      • createManagedAutoplaylist: (
            name: string,
            query: string,
            sort?: string,
            keepSorted?: boolean,
        ) => Promise<PlaylistCreateManagedAutoplaylistResponse>

        Create an autoplaylist with editable query and sorting rules. It requires this component to remain installed. Success returns the configuration, without waiting for track rebuilding or disk persistence.

      • deselectAll: (playlist: PlaylistRef) => Promise<PlaylistDeselectAllResponse>

        Deselect all tracks in a playlist.

      • duplicate: (playlist: PlaylistRef, name?: string) => Promise<PlaylistDuplicateResponse>

        name omitted or empty, the copy is named after the original with (Copy) appended.

      • focusTrack: (
            playlist: PlaylistRef,
            trackIndex: number,
        ) => Promise<PlaylistFocusTrackResponse>

        Use playlist.setFocused.

      • getActive: () => Promise<PlaylistGetActiveResponse>

        Resolve with found: false and no other fields when there is no active playlist.

      • getAll: () => Promise<PlaylistGetAllResponse>

        Every playlist in playlist order, in playlists.

      • getAutoplaylistConfig: (playlist: PlaylistRef) => Promise<PlaylistGetAutoplaylistConfigResponse>

        Read this component's managed autoplaylist configuration and revision. Other providers return a failure envelope. Use configAvailability from getAutoplaylistInfo to decide whether to offer a configuration form.

      • getAutoplaylistInfo: (playlist: PlaylistRef) => Promise<PlaylistGetAutoplaylistInfoResponse>

        Inspect autoplaylist state and editor availability without opening UI. unknown means the provider has no capability probe. source: 'sdk' includes third-party clients; source: 'dui' identifies an Auto-named lock, not a UI mode. That lock's keepSorted: false is an unreadable setting's placeholder, not its actual value. configAvailability separately reports structured configuration support.

      • getAutoplaylistQuery: (playlist: PlaylistRef) => Promise<PlaylistGetAutoplaylistQueryResponse>

        Read autoplaylist state with its query and sort. Both are read live from foobar2000's built-in query/sort client and are null for any other provider, a list managed by this component (use getAutoplaylistConfig), or a configuration that cannot be parsed; note says which. Test query before sort, which older hosts omit. Editor capability is available from getAutoplaylistInfo. The same provider-source and unreadable keepSorted rules apply here.

      • getAvailableColumns: () => Promise<PlaylistGetAvailableColumnsResponse>

        The Default UI playlist columns, in columns.

      • getCount: (playlist: PlaylistRef) => Promise<PlaylistGetTrackCountResponse>

        Number of tracks in playlist, sent as the host's playlist.getTrackCount; the envelope carries it in count. Resolves with count 0 when the playlist does not exist. The number of playlists is playlist.getPlaylistCount, which is what the host's playlist.getCount returns.

      • getFocused: (playlist: PlaylistRef) => Promise<PlaylistGetFocusedTrackResponse>

        index is -1 when the playlist has no focus or does not exist.

      • getFocusTrack: (playlist: PlaylistRef) => Promise<PlaylistGetFocusTrackResponse>

        Use playlist.getFocused.

      • getGroupRuns: (
            patterns: string[],
            playlist?: PlaylistRef,
        ) => Promise<PlaylistGetGroupRunsResponse>

        Group a whole playlist into consecutive runs and get back only the run boundaries, never the rows.

        A run is a maximal stretch of adjacent tracks whose group key is equal, compared case-insensitively over ASCII A-Z/a-z. Rows are never reordered, so runs follow playlist order. Pass one Title Formatting pattern, or two to sub-group within each run.

        Pair it with playlist.getTracks to drive a grouped virtual list: the runs give header positions and total scroll height, each visible page of rows is fetched separately.

        A pattern that groups every row on its own makes runs as long as total. Payload size also depends on key lengths and second-level runs. There is no cap; choose patterns that combine adjacent tracks.

        Malformed patterns, or a pattern that fails to compile, resolves with { success: false, code: 'INVALID_PARAMS' }; for an empty pattern or one that fails to compile, details.pattern carries its index. An index past the last playlist resolves with INVALID_INDEX.

      • getLockInfo: (playlist: PlaylistRef) => Promise<PlaylistGetLockInfoResponse>

        Describe a playlist's lock status, lock name, and what the lock forbids.

      • getMatchingRows: (
            query: string,
            playlist?: PlaylistRef,
        ) => Promise<PlaylistGetMatchingRowsResponse>

        The rows of a playlist whose tracks match a foobar2000 query, as { playlist, playlistGuid, total, items, count } with items ascending; one call however long the playlist is. Read the rows with playlist.getTracksAt.

        A query the parser rejects, or one carrying SORT BY, resolves with { success: false, code: 'INVALID_PARAMS', details: { param: 'query' } }; the error text is in the host's language. A lowercase letter matches either case in the tag, an uppercase one only the same case. The answer is a snapshot: drop it on playlist:itemsAdded, itemsRemoved, itemsReordered, itemsReplaced and metadb:changed. A query that depends on the time (DURING LAST) also drifts with no event.

      • getPlaying: () => Promise<PlaylistGetPlayingResponse>

        Resolve with found: false and no other fields when nothing is playing.

      • getPlaylistCount: () => Promise<PlaylistGetCountResponse>

        Number of playlists, sent as the host's playlist.getCount; the envelope carries it in count. For the number of tracks in one playlist use playlist.getCount.

      • getSelectedTracks: (playlist: PlaylistRef) => Promise<PlaylistGetSelectedTracksResponse>

        The selected tracks of a playlist, as { playlist, count, tracks }. Rows are whole PlaylistTracks without the play statistics. An empty selection succeeds with an empty tracks; a playlist that does not exist resolves with a failure envelope.

      • getSelection: (playlist: PlaylistRef) => Promise<PlaylistGetSelectionResponse>

        Report the 0-based indices of all selected tracks in a playlist.

      • getTracks: (
            playlist: PlaylistRef,
            start?: number,
            count?: number,
            formats?: Record<string, string>,
            fields?: string[],
        ) => Promise<PlaylistGetTracksResponse>

        Fetch a slice of tracks from a playlist, as the page { playlist, start, count, total, tracks }.

        Without fields each row is a whole PlaylistTrack, with the play statistics foo_playcount provides. fields narrows every row to the requested keys plus index, out of the same case-sensitive list library.query takes, which is why rows are typed as PlaylistTrackPartial. formats maps column names to Title Formatting patterns; each row carries their values under formats. An unknown field name resolves with { success: false, code: 'INVALID_PARAMS' }.

        Compare total with playlist.getGroupRuns's total for the same playlist to detect a change in track count between the reads. Equal totals do not rule out replacements or reordering: the calls return independent snapshots, not a shared playlist revision.

      • getTracksAt: (
            playlist: PlaylistRef,
            rows: readonly number[],
            formats?: Record<string, string>,
            fields?: string[],
        ) => Promise<PlaylistGetTracksAtResponse>

        Rows of a playlist picked by row number, as { playlist, total, count, tracks }, the rows in the order given. Rows past the last one are skipped and every row carries its index, so match rows by index rather than by position in tracks. formats and fields work as in playlist.getTracks; a playlist that does not exist answers an empty result, as there.

      • getTracksPage: (
            playlist: PlaylistRef,
            start?: number,
            count?: number,
            formats?: Record<string, string>,
            fields?: string[],
        ) => Promise<PlaylistGetTracksResponse>

        Use playlist.getTracks, which resolves with the same page.

      • insertTracks: (
            playlist: PlaylistRef,
            insertIndex: number,
            handles: PlaylistHandleRef[],
            expectedVersion?: string,
        ) => Promise<PlaylistInsertTracksResponse>

        Insert tracks before row insertIndex; past the last row, they are appended.

      • isAutoplaylist: (playlist: PlaylistRef) => Promise<PlaylistIsAutoplaylistResponse>

        Report whether a playlist is an autoplaylist or carries an automatic-playlist lock.

      • isLocked: (playlist: PlaylistRef) => Promise<PlaylistIsLockedResponse>

        Report whether a playlist carries a lock (e.g. from an autoplaylist).

      • moveTracks: (
            playlist: PlaylistRef,
            indices: number[],
            delta: number,
            expectedVersion?: string,
        ) => Promise<PlaylistMoveTracksResponse>

        Replace the selection with indices, then move the selection by delta rows; the caller's own selection is lost. An empty indices moves the current selection.

      • onAutoplaylistConfigChanged: (
            callback: (event: PlaylistAutoplaylistConfigChangedPayload) => void,
        ) => () => void

        Observe managed configuration changes from all component windows. Re-read the snapshot before editing; this does not signal completion of track rebuilding or disk persistence. Returns an unsubscribe function.

      • onAutoplaylistUIResult: (callback: (event: PlaylistAutoplaylistUIResultPayload) => void) => () => void

        Subscribe to native editor call results for this calling document. Subscribe before showAutoplaylistUI and retain early events by operationId in a bounded buffer until acceptance is handled. Success only means the native call returned normally, not that an editor opened, closed or saved changes. Results are not forwarded after navigation. Returns the unsubscribe function; call it when the consumer is disposed.

      • playTrack: (
            playlist: PlaylistRef,
            trackIndex: number,
            options?: Omit<
                PlaylistPlayTrackParams,
                "index"
                | "playlist"
                | "playlistGuid",
            >,
        ) => Promise<PlaylistPlayTrackResponse>

        Start playing the track at the specified index in a playlist.

      • redo: (playlist: PlaylistRef) => Promise<PlaylistRedoResponse>

        Fails with NOT_FOUND when there is nothing to redo.

      • remove: (playlist: PlaylistRef) => Promise<PlaylistRemoveResponse>

        Delete a playlist.

      • removeAutoplaylist: (playlist: PlaylistRef) => Promise<PlaylistRemoveAutoplaylistResponse>

        Release an autoplaylist-manager client, keeping the current tracks.

      • removeSelectedTracks: (playlist: PlaylistRef) => Promise<PlaylistRemoveSelectedTracksResponse>

        Remove all selected tracks from a playlist, saving an undo point first.

      • removeTracks: (
            playlist: PlaylistRef,
            indices: number[],
            expectedVersion?: string,
        ) => Promise<PlaylistRemoveTracksResponse>

        Remove rows; rows past the last one are ignored.

      • rename: (playlist: PlaylistRef, name: string) => Promise<PlaylistRenameResponse>

        Rename a playlist.

      • reorder: (
            playlist: PlaylistRef,
            order: number[],
            expectedVersion?: string,
        ) => Promise<PlaylistReorderResponse>

        order[i] is the current row of the track that moves to row i.

      • reorderPlaylists: (
            order: readonly string[] | readonly number[],
        ) => Promise<PlaylistReorderPlaylistsResponse>

        Reorder the playlist list. order[i] names the playlist that moves to position i, every playlist exactly once: all current indices, sent as newOrder, or all guids from playlist.getAll, sent as newOrderGuids. Indices are read as the call arrives, so an order built from an earlier getAll silently moves the wrong playlists once another one was added and removed in between; GUIDs keep naming the playlists they were read from and fail with NOT_FOUND for one that is gone.

      • replaceAllAndPlay: (
            options: PlaylistReplaceAllAndPlayParams,
        ) => Promise<PlaylistReplaceAllAndPlayResponse>

        Stop, clear, add the paths in the given order, activate the playlist and play or focus playIndex, counted in that order. When nothing could be added the call fails with NOT_FOUND and the playlist stays empty.

      • reverse: (playlist: PlaylistRef) => Promise<PlaylistReverseResponse>

        Reverse track order in a playlist, saving an undo point first.

      • selectAll: (playlist: PlaylistRef) => Promise<PlaylistSelectAllResponse>

        Select all tracks in a playlist.

      • setActive: (playlist: PlaylistRef) => Promise<PlaylistSetActiveResponse>

        Make a playlist the active one.

      • setAutoplaylistConfig: (
            playlist: PlaylistRef,
            options: Omit<
                PlaylistSetAutoplaylistConfigParams,
                "playlist"
                | "playlistGuid",
            >,
        ) => Promise<PlaylistSetAutoplaylistConfigResponse>

        Edit rules using the revision from a recent configuration snapshot. Omitted fields stay unchanged; an empty sort clears it and false disables keep-sorted. Host failures can leave partial changes: inspect the failure envelope and re-read before retrying. A revision is not a track version.

      • setFocused: (
            playlist: PlaylistRef,
            trackIndex: number,
            expectedVersion?: string,
        ) => Promise<PlaylistSetFocusedTrackResponse>

        A negative trackIndex removes the focus.

      • setSelection: (
            playlist: PlaylistRef,
            indices: number[],
            clearOthers?: boolean,
            expectedVersion?: string,
        ) => Promise<PlaylistSetSelectionResponse>

        Rows past the last one are ignored; a negative row fails with INVALID_PARAMS.

      • showAutoplaylistUI: (playlist: PlaylistRef) => Promise<PlaylistShowAutoplaylistUIResponse>

        Request the native editor for an explicitly named autoplaylist. A numeric index selects the playlist at that position when first handled by the host; subsequent work follows its GUID. Pass a GUID to preserve identity before that first lookup. Does not activate the playlist or play.

        Resolves with acceptance or a business failure envelope, without waiting for the native call to return or the editor to close. Subscribe with onAutoplaylistUIResult before calling: a result can arrive before this promise is handled. Match it by operationId; it does not report saving or cancellation. Navigation or destruction discards result delivery.

      • shuffle: (playlist: PlaylistRef) => Promise<PlaylistShuffleResponse>

        Randomly shuffle tracks in a playlist, saving an undo point first.

      • sort: (
            playlist: PlaylistRef,
            pattern: string,
            descending?: boolean,
            selectedOnly?: boolean,
        ) => Promise<PlaylistSortResponse>

        descending reverses the whole playlist after sorting, the unselected tracks too when selectedOnly is set.

      • undo: (playlist: PlaylistRef) => Promise<PlaylistUndoResponse>

        Fails with NOT_FOUND when there is nothing to undo.

    • port: {
          connect: (name: string) => Promise<PortConnectResponse>;
          disconnect: (portId: string) => Promise<PortDisconnectResponse>;
          getPorts: (name?: string) => Promise<PortGetPortsResponse>;
          onConnect: (handler: (data: unknown) => void) => () => void;
          onDisconnect: (handler: (data: unknown) => void) => () => void;
          onMessage: (handler: (data: unknown) => void) => () => void;
          postMessage: (
              portId: string,
              message: JsonValue,
          ) => Promise<PortPostMessageResponse>;
          postMessageTo: (
              portId: string,
              targetPortId: string,
              message: JsonValue,
          ) => Promise<PortPostMessageToResponse>;
      }

      port — cross-window named-channel messaging hub.

      Use port.connect to obtain a portId; subsequent port.postMessage / port.postMessageTo calls route via that handle. Receivers subscribe with port.onMessage.

      • connect: (name: string) => Promise<PortConnectResponse>

        Open a port on a named channel for the calling window and announce it with port:connected.

      • disconnect: (portId: string) => Promise<PortDisconnectResponse>

        Close a port and announce it with port:disconnected.

      • getPorts: (name?: string) => Promise<PortGetPortsResponse>

        Omit name to list the ports of every channel.

      • onConnect: (handler: (data: unknown) => void) => () => void

        Subscribe to port connection events. Returns an unsubscribe function.

      • onDisconnect: (handler: (data: unknown) => void) => () => void

        Subscribe to port disconnection events. Returns an unsubscribe function.

      • onMessage: (handler: (data: unknown) => void) => () => void

        Subscribe to incoming messages on ports. Returns an unsubscribe function.

      • postMessage: (portId: string, message: JsonValue) => Promise<PortPostMessageResponse>

        null is not a message; the host refuses it as missing.

      • postMessageTo: (
            portId: string,
            targetPortId: string,
            message: JsonValue,
        ) => Promise<PortPostMessageToResponse>

        Send a message to one port, as a port:message event to that port's window.

    • queue: {
          add: (opts: QueueAddParams) => Promise<QueueAddResponse>;
          addPaths: (
              paths: string[],
              opts?: Omit<QueueAddPathsParams, "paths">,
          ) => Promise<QueueAddPathsResponse>;
          clear: () => Promise<QueueClearResponse>;
          flush: () => Promise<QueueFlushResponse>;
          get: () => Promise<QueueGetResponse>;
          getCount: () => Promise<QueueGetCountResponse>;
          insertNext: (
              entries: (string | QueueListRef)[],
              position?: number,
              expectedVersion?: string,
          ) => Promise<QueueInsertNextResponse>;
          moveToTop: (
              index: number,
              expectedVersion?: string,
          ) => Promise<QueueMoveToTopResponse>;
          playNow: (
              index?: number,
              expectedVersion?: string,
          ) => Promise<QueuePlayNowResponse>;
          remove: (
              target: number | number[],
              expectedVersion?: string,
          ) => Promise<QueueRemoveResponse>;
          setContents: (
              items: QueueContentRef[],
              expectedVersion?: string,
          ) => Promise<QueueSetContentsResponse>;
      }

      queue — foobar2000 play-queue namespace (not to be confused with the just-in-time queue exposed via jitQueue).

      • add: (opts: QueueAddParams) => Promise<QueueAddResponse>

        Fails with INVALID_INDEX when no given position is in range.

      • addPaths: (
            paths: string[],
            opts?: Omit<QueueAddPathsParams, "paths">,
        ) => Promise<QueueAddPathsResponse>

        Add the given paths to the play queue. Each path/URL is capped at 2048 chars; over-length items are silently skipped and counted in invalidCount.

      • clear: () => Promise<QueueClearResponse>

        Clear all items from the play queue.

      • flush: () => Promise<QueueFlushResponse>

        Clear the play queue. Same as queue.clear.

      • get: () => Promise<QueueGetResponse>

        Every entry is the shared Track row plus queueIndex, playlist and playlistItem.

      • getCount: () => Promise<QueueGetCountResponse>

        Report how many entries the queue holds.

      • insertNext: (
            entries: (string | QueueListRef)[],
            position?: number,
            expectedVersion?: string,
        ) => Promise<QueueInsertNextResponse>

        Insert tracks so they play next, ahead of everything already queued.

        An entry is either a path string (path|subsong:N accepted) or a QueueListRef playlist coordinate, and one array may hold both. The two forms travel as separate blocks: at the target position the coordinate entries land first, then the path entries, each block in the order it was given. A mixed array therefore loses its interleaving — [p1, I1, p2] reaches the queue as I1, p1, p2. To commit an exact interleaved order, call this and then queue.setContents with the order wanted.

        An entry whose track is already queued moves to its new position instead of being queued a second time, and only one queued entry moves per track: for a coordinate, the entry holding that exact coordinate if there is one, otherwise the first entry of the track, which then takes the coordinate given; for a path, the first entry of the track. Tracks not already queued are inserted as new entries. Other queued copies remain in place. position is the index within the queue after any moved entries have been removed, and defaults to 0 (the very front).

        All input entries are de-duplicated by track. For duplicate coordinates, the first one already present in the queue is retained; if none matches, the first supplied coordinate is used. The track's position within the input block remains its first occurrence. Unlike queue.add and queue.setContents, two references to one track therefore produce one entry. insertedCount + movedCount can be below entries.length because of de-duplication or invalid paths; a folder or container path can also expand to multiple tracks.

        A coordinate that does not address a queueable playlist item, or names a playlistGuid no playlist has (NOT_FOUND), fails the whole call before anything is written; the paths passed in the same call are not queued either.

        The response separates insertedCount (new tracks), movedCount (existing entries relocated). invalidCount is input path count minus resolved track count, floored at zero. Folder or container expansion can hide failed paths in that difference. Coordinates are excluded; a bad coordinate fails the call outright.

        A newly queued path has no playlist coordinates, so playback cannot continue from that track's position in a playlist. Moving an existing entry by path preserves its usable coordinate. Pass a QueueListRef to select a particular playlist position.

        A path that reached the queue through the path|subsong:N suffix accepted by the older queue.addPaths call may fail to match as "already queued" here; this only affects tracks queued before upgrading, not new calls. A bare path to a multi-subsong file and that same path with an explicit |subsong:0 suffix are also treated as distinct identities rather than equivalent.

      • moveToTop: (index: number, expectedVersion?: string) => Promise<QueueMoveToTopResponse>

        Move the entry at index to the front; 0 is refused.

      • playNow: (index?: number, expectedVersion?: string) => Promise<QueuePlayNowResponse>

        Play the queue entry at index immediately, moving it to the front of the queue first if it is not already there.

        Defaults to index: 0 (the current queue head). Fails with NOT_FOUND when nothing is queued, or INVALID_INDEX for an out-of-range value.

        queueCount is read immediately after playback starts; the host does not guarantee that its consumption of the queue head happens synchronously with that read, so the value may reflect the queue either just before or just after the played entry is removed. Call queue.getCount afterward if the exact post-play length matters.

      • remove: (
            target: number | number[],
            expectedVersion?: string,
        ) => Promise<QueueRemoveResponse>

        Remove queue entries: one position, sent as index, or an array of positions, sent as indices and removed in one call. In an array, duplicate and out-of-range positions are skipped and removedCount reports how many entries went. Fails with INVALID_INDEX when no given position is in range.

      • setContents: (
            items: QueueContentRef[],
            expectedVersion?: string,
        ) => Promise<QueueSetContentsResponse>

        Replace the entire queue with the given ordered list of references.

        Every entry must resolve to { queueIndex } (keep/reorder an existing queue slot) or { playlist, item } / { playlistGuid, item } (add a playlist track); an unrecognized entry shape, or a playlistGuid no playlist has (NOT_FOUND), fails the whole call before anything is written, unlike queue.add, which skips bad entries one at a time. Passing an empty array clears the queue, equivalent to queue.clear.

        items.length is capped at max(256, current queue length); exceeding the cap fails without changing the queue.

        Intended for a single commit at the end of a drag-to-reorder gesture, not for per-frame calls while dragging — each call flushes and rebuilds the queue from scratch.

    • rating: {
          get: (
              path: string,
              opts?: { cueIndex?: number },
          ) => Promise<RatingGetResponse>;
          set: (
              path: string,
              rating: number,
              opts?: { cueIndex?: number },
          ) => Promise<RatingSetResponse>;
      }

      rating — track rating namespace (0-5 integer scale).

      • get: (path: string, opts?: { cueIndex?: number }) => Promise<RatingGetResponse>

        Resolve the 0-5 integer rating stored for the track at path.

        Uses %rating% when its atoi conversion yields 1 to 5; otherwise reads the file's RATING tag and clamps it to 0-5. 0 means unrated. storage is 'stats' for an accepted %rating% value and 'file' otherwise, including when neither source provides a rating.

      • set: (
            path: string,
            rating: number,
            opts?: { cueIndex?: number },
        ) => Promise<RatingSetResponse>

        Set the 0-5 integer rating for the track at path.

    • Readonlyready: () => Promise<void>
    • replaygain: {
          clear: (paths: string[]) => Promise<ReplaygainClearResponse>;
          get: (paths: string | string[]) => Promise<ReplaygainGetResponse>;
          getMode: () => Promise<ReplaygainGetModeResponse>;
          getPreamp: () => Promise<ReplaygainGetPreampResponse>;
          getSettings: () => Promise<ReplaygainGetSettingsResponse>;
          scan: (
              paths: string[],
              opts?: { mode?: "track" | "album" },
          ) => Promise<ReplaygainScanResponse>;
          setMode: (
              sourceMode: NonNullable<
                  "auto"
                  | "none"
                  | "track"
                  | "album"
                  | "byPlaybackOrder"
                  | undefined,
              >,
              processingMode?: "gain" | "none" | "peak" | "gain_and_peak",
          ) => Promise<ReplaygainSetModeResponse>;
          setPreamp: (
              withRg?: number,
              withoutRg?: number,
          ) => Promise<ReplaygainSetPreampResponse>;
      }

      replaygain — ReplayGain mode / preamp / scan namespace.

      • clear: (paths: string[]) => Promise<ReplaygainClearResponse>

        Remove ReplayGain values from the specified files.

      • get: (paths: string | string[]) => Promise<ReplaygainGetResponse>

        Accepts a single path or an array; always sent as { paths: string[] }.

      • getMode: () => Promise<ReplaygainGetModeResponse>

        Read the ReplayGain source mode and processing mode.

      • getPreamp: () => Promise<ReplaygainGetPreampResponse>

        Read the two ReplayGain preamps, in dB.

      • getSettings: () => Promise<ReplaygainGetSettingsResponse>

        Read the complete ReplayGain configuration: modes, preamps, and active status.

      • scan: (
            paths: string[],
            opts?: { mode?: "track" | "album" },
        ) => Promise<ReplaygainScanResponse>

        Trigger a ReplayGain scan over the given paths via the host's context-menu pipeline.

      • setMode: (
            sourceMode: NonNullable<
                "auto"
                | "none"
                | "track"
                | "album"
                | "byPlaybackOrder"
                | undefined,
            >,
            processingMode?: "gain" | "none" | "peak" | "gain_and_peak",
        ) => Promise<ReplaygainSetModeResponse>

        Change the ReplayGain source mode, processing mode, or both.

      • setPreamp: (withRg?: number, withoutRg?: number) => Promise<ReplaygainSetPreampResponse>

        Change one or both ReplayGain preamps in dB.

    • selection: {
          get: (opts?: SelectionGetParams) => Promise<SelectionGetResponse>;
          getType: () => Promise<SelectionGetTypeResponse>;
          getViewerMode: () => Promise<SelectionGetViewerModeResponse>;
          getViewingTrack: (
              opts?: SelectionGetViewingTrackParams,
          ) => Promise<SelectionGetViewingTrackResponse>;
          set: (handles: string[]) => Promise<SelectionSetResponse>;
          setPlaylistTracking: (
              mode?: NonNullable<"playlist" | "selection" | undefined>,
          ) => Promise<SelectionSetPlaylistTrackingResponse>;
      }

      selection — current selection / viewer-mode namespace.

      • get: (opts?: SelectionGetParams) => Promise<SelectionGetResponse>

        Omitting limit caps the page at 100 and reports truncated; limit: 0 returns everything.

      • getType: () => Promise<SelectionGetTypeResponse>

        Report the type of the current global selection, as a numeric index and name.

      • getViewerMode: () => Promise<SelectionGetViewerModeResponse>

        Report which source the user's Selection Viewer preference favours (prefer_playing or prefer_selection).

      • getViewingTrack: (
            opts?: SelectionGetViewingTrackParams,
        ) => Promise<SelectionGetViewingTrackResponse>

        With includeTrackInfo the response carries the shared Track row as track.

      • set: (handles: string[]) => Promise<SelectionSetResponse>

        Replace the global selection with the given track paths. Handles can have |subsong:N suffixes.

      • setPlaylistTracking: (
            mode?: NonNullable<"playlist" | "selection" | undefined>,
        ) => Promise<SelectionSetPlaylistTrackingResponse>

        Takes the selection from the active playlist: its selected rows with 'selection' (default), all of it with 'playlist'. Taken once; the host does not keep tracking after the call.

    • sharedState: {
          delete: (key: string) => Promise<StateDeleteResponse>;
          get: (key: string) => Promise<StateGetResponse>;
          keys: (pattern?: string) => Promise<StateKeysResponse>;
          onChange: (handler: (data: unknown) => void) => () => void;
          onDelete: (handler: (data: unknown) => void) => () => void;
          set: (
              key: string,
              value: JsonValue,
              silent?: boolean,
              ttlMs?: number,
          ) => Promise<StateSetResponse>;
      }

      sharedState — cross-window key/value state store.

      Distinct from state (the reactive playback mirror): this is a shared persistent / TTL-bound key/value bag with change events. Events use the state:* colon namespace.

      • delete: (key: string) => Promise<StateDeleteResponse>

        Remove a key from the shared state store.

      • get: (key: string) => Promise<StateGetResponse>

        Read a value from the cross-window shared state store by key.

      • keys: (pattern?: string) => Promise<StateKeysResponse>

        List keys in the shared state store matching an optional glob pattern.

      • onChange: (handler: (data: unknown) => void) => () => void

        Subscribe to shared state change events. Returns an unsubscribe function.

      • onDelete: (handler: (data: unknown) => void) => () => void

        Subscribe to shared state deletion events. Returns an unsubscribe function.

      • set: (
            key: string,
            value: JsonValue,
            silent?: boolean,
            ttlMs?: number,
        ) => Promise<StateSetResponse>

        ttlMs is the lifetime in milliseconds. null is not a value; remove a key with sharedState.delete instead.

    • shell: {
          exec: (
              command: string,
              options?: Omit<ShellExecParams, "command">,
          ) => Promise<ShellExecResponse>;
          openExternal: (url: string) => Promise<ShellOpenExternalResponse>;
          openWith: (path: string) => Promise<ShellOpenWithResponse>;
          showInExplorer: (path: string) => Promise<ShellShowInExplorerResponse>;
          spawn: (
              executable: string,
              options?: Omit<ShellSpawnParams, "executable">,
          ) => Promise<ShellSpawnResponse>;
      }

      shell — OS-level integration namespace.

      Note: spawn short-circuits with { success: false } when an empty cwd string is passed.

      • exec: (
            command: string,
            options?: Omit<ShellExecParams, "command">,
        ) => Promise<ShellExecResponse>

        Start a process from a command line and return at once.

      • openExternal: (url: string) => Promise<ShellOpenExternalResponse>

        Open an http, https, or mailto URL with the default handler.

      • openWith: (path: string) => Promise<ShellOpenWithResponse>

        Open a file with the application Windows associates with its type.

      • showInExplorer: (path: string) => Promise<ShellShowInExplorerResponse>

        Reveal a file or folder in Windows Explorer, selecting it.

      • spawn: (
            executable: string,
            options?: Omit<ShellSpawnParams, "executable">,
        ) => Promise<ShellSpawnResponse>

        Start a process from an executable and an argument list.

    • state: ReactiveState

      Singleton reactive playback-state mirror. Mutated by the event handlers wired below.

    • system: {
          getApisByNamespace: (
              namespace: string,
          ) => Promise<SystemGetApisByNamespaceResponse>;
          getApiStats: () => Promise<SystemGetApiStatsResponse>;
          getDPI: () => Promise<SystemGetDPIResponse>;
          getLocale: () => Promise<SystemGetLocaleResponse>;
          getRegisteredPlugins: () => Promise<SystemGetRegisteredPluginsResponse>;
          getTheme: () => Promise<SystemGetThemeResponse>;
          isPluginRegistered: (
              namespace: string,
          ) => Promise<SystemIsPluginRegisteredResponse>;
          listApis: (
              includeInternal?: boolean,
              includeExternal?: boolean,
          ) => Promise<SystemListAvailableApisResponse>;
          searchApis: (query: string) => Promise<SystemSearchApisResponse>;
      }

      system — API discovery / plugin / locale namespace.

    • taskbar: {
          flash: (opts?: TaskbarFlashParams) => Promise<TaskbarFlashResponse>;
          setOverlayIcon: (
              opts?: TaskbarSetOverlayIconParams,
          ) => Promise<TaskbarSetOverlayIconResponse>;
          setProgress: (
              opts: TaskbarSetProgressParams,
          ) => Promise<TaskbarSetProgressResponse>;
          setThumbnailButtons: (
              buttons: ThumbnailButton[],
          ) => Promise<TaskbarSetThumbnailButtonsResponse>;
          updateButton: (
              opts: TaskbarUpdateButtonParams,
          ) => Promise<TaskbarUpdateButtonResponse>;
      }

      taskbar namespace - Windows taskbar thumbnail toolbar, progress bar, overlay icon and flash bindings.

      Parameter and response shapes come from src/api/schema/taskbar.ts through the generated types; see the taskbar-tray page of the API reference.

    • titleformat: {
          eval: (
              pattern: string,
              path?: string,
          ) => Promise<TitleformatEvalResponse>;
          evalBatch: (
              pattern: string,
              paths: string[],
          ) => Promise<TitleformatEvalBatchResponse>;
          evalFields: (
              path: string,
              fields: TitleformatFieldMap,
          ) => Promise<TitleformatEvalFieldsResponse>;
          evalFieldsBatch: (
              paths: string[],
              fields: TitleformatFieldMap,
          ) => Promise<TitleformatEvalFieldsBatchResponse>;
          getBuiltinFields: () => Promise<TitleformatGetBuiltinFieldsResponse>;
      }

      titleformat — title-format script evaluation namespace.

      • eval: (pattern: string, path?: string) => Promise<TitleformatEvalResponse>

        Evaluate a single pattern against one track, or against the playing track when path is omitted or empty. Evaluating the playing track also fills dynamic fields such as %playback_time% and stream titles; with nothing playing it resolves success: false with code: 'NO_ACTIVE_ITEM'.

        infoAvailable: false means the host could not get the track's info (a remote path with nothing cached, or an unreadable file), so tag-derived output is untrustworthy. See the SDK docs for what the flag does not cover.

      • evalBatch: (pattern: string, paths: string[]) => Promise<TitleformatEvalBatchResponse>

        Batch variant of eval(). Each row carries its own infoAvailable flag; rows that failed omit it.

      • evalFields: (
            path: string,
            fields: TitleformatFieldMap,
        ) => Promise<TitleformatEvalFieldsResponse>

        Evaluate one or more named patterns against a single track. The fields argument maps each output key to a titleformat pattern string (e.g. { artist: '%artist%', year: '$year(%date%)' }).

        infoAvailable: false means tag-derived values are untrustworthy, under the same conditions as eval. One flag covers the whole merged script and never covers foo_playcount virtual fields — see the SDK docs for the full limitation. Keys of fields named success, path or infoAvailable are dropped because the response fields of those names take precedence; keys named error or code are kept, so check success to tell a failure.

      • evalFieldsBatch: (
            paths: string[],
            fields: TitleformatFieldMap,
        ) => Promise<TitleformatEvalFieldsBatchResponse>

        Batch variant of evalFields. Compiles the merged pattern once and applies it to every path — host-side optimisation gives roughly 10× speedup vs. calling evalFields per track.

        Each row carries its own infoAvailable flag with the same meaning and the same merged-script limitation as evalFields. Keys of fields named path, success or infoAvailable are dropped from each row; a key named error is kept, so check the row's success.

      • getBuiltinFields: () => Promise<TitleformatGetBuiltinFieldsResponse>

        List commonly used title formatting fields, keyed by a readable name.

    • tray: {
          appendMenuItems: (
              items: TrayMenuItem[],
              position?: TrayMenuPosition,
          ) => Promise<TrayAppendMenuItemsResponse>;
          clearMenuItems: (
              position?: TrayMenuPosition,
          ) => Promise<TrayClearMenuItemsResponse>;
          create: (
              opts?: { icon?: string | null; tooltip?: string },
          ) => Promise<TrayCreateResponse>;
          destroy: () => Promise<TrayDestroyResponse>;
          getMenuItems: () => Promise<TrayGetMenuItemsResponse>;
          isVisible: () => Promise<TrayIsVisibleResponse>;
          removeMenuItems: (ids: string[]) => Promise<TrayRemoveMenuItemsResponse>;
          setClickAction: (
              action: "event" | "toggleMainWindow",
          ) => Promise<TraySetClickActionResponse>;
          setCloseToTray: (enabled: boolean) => Promise<TraySetCloseToTrayResponse>;
          setContextMenu: (
              items: TrayMenuItem[],
              config?: TrayMenuConfig,
          ) => Promise<TraySetContextMenuResponse>;
          setIcon: (icon?: string | null) => Promise<TraySetIconResponse>;
          setMenuItemState: (
              id: string,
              state: { checked?: boolean; enabled?: boolean },
          ) => Promise<TraySetMenuItemStateResponse>;
          setMenuZones: (
              zones: Omit<TraySetMenuZonesParams, "config">,
              config?: TrayMenuConfig,
          ) => Promise<TraySetMenuZonesResponse>;
          setMinimizeToTray: (
              enabled: boolean,
          ) => Promise<TraySetMinimizeToTrayResponse>;
          setTooltip: (tooltip: string) => Promise<TraySetTooltipResponse>;
          showBalloon: (
              opts: {
                  icon?: "error" | "info" | "warning";
                  message: string;
                  title: string;
              },
          ) => Promise<TrayShowBalloonResponse>;
      }

      tray namespace - system tray icon bindings.

      See the taskbar-tray page of the API reference for the full contract.

      • appendMenuItems: (
            items: TrayMenuItem[],
            position?: TrayMenuPosition,
        ) => Promise<TrayAppendMenuItemsResponse>

        Append items to the given zone (default 'top').

      • clearMenuItems: (position?: TrayMenuPosition) => Promise<TrayClearMenuItemsResponse>

        Clear the given zone, or all zones if position is omitted.

      • create: (
            opts?: { icon?: string | null; tooltip?: string },
        ) => Promise<TrayCreateResponse>

        Create the tray icon, preserving any previously configured click action.

      • destroy: () => Promise<TrayDestroyResponse>

        Remove the icon, cancel pending clicks and reset the click action to event.

      • getMenuItems: () => Promise<TrayGetMenuItemsResponse>

        Get all user-defined menu items, flattened in zone order (top -> playback -> bottom). Built-in items injected by showPlaybackControls / showSystemItems are not included.

      • isVisible: () => Promise<TrayIsVisibleResponse>

        Resolve whether the tray icon currently exists.

      • removeMenuItems: (ids: string[]) => Promise<TrayRemoveMenuItemsResponse>

        Remove items with the given ids from all zones, submenus included. Resolves with the number removed.

      • setClickAction: (action: "event" | "toggleMainWindow") => Promise<TraySetClickActionResponse>

        Select the process-wide left-click action, even before creating the icon. event preserves existing click notifications. toggleMainWindow handles each gesture natively, including while the page is suspended, and emits neither click nor double-click events. It preserves window placement and tray settings. Every call cancels pending clicks; the latest successful caller wins. Remove click handlers that issue window commands before enabling native mode; events already queued in a page cannot be recalled. Panel mode is unsupported.

      • setCloseToTray: (enabled: boolean) => Promise<TraySetCloseToTrayResponse>

        Hide to the tray instead of quitting when the window is closed.

      • setContextMenu: (
            items: TrayMenuItem[],
            config?: TrayMenuConfig,
        ) => Promise<TraySetContextMenuResponse>

        Replace the items of the zone determined by config.customPosition (default 'top'). The other two zones are left intact. Use setMenuZones to replace every zone at once, and the incremental helpers below for partial updates.

      • setIcon: (icon?: string | null) => Promise<TraySetIconResponse>

        Replace the tray icon image; omit or pass null to fall back to the main icon.

      • setMenuItemState: (
            id: string,
            state: { checked?: boolean; enabled?: boolean },
        ) => Promise<TraySetMenuItemStateResponse>

        Update a single menu item's checked / enabled state in place. The id is searched across all zones and recursively into submenus. At least one of checked / enabled must be supplied. This is a granular alternative to setContextMenu, which performs a full-zone replace.

        Providing checked (true or false) marks the item checkable so subsequent getMenuItems() and the WebView overlay keep checkbox semantics even when the value is false.

        The native tray menu is rebuilt from stored data each time it is opened, so the new state takes effect on the next open rather than mutating a menu that is already showing. An id no row has fails with NOT_FOUND.

      • setMenuZones: (
            zones: Omit<TraySetMenuZonesParams, "config">,
            config?: TrayMenuConfig,
        ) => Promise<TraySetMenuZonesResponse>

        Replace the items of all three zones in one call; a zone left out is cleared. The built-in items of showPlaybackControls and showSystemItems are not stored in the zones and stay. When an item is rejected or the resource limits are exceeded, nothing is stored, config included.

        Prefer this to clearMenuItems followed by appendMenuItems when the whole menu changes: a menu opened between those calls shows part of the update, and two such updates that interleave add their items twice. Of two calls sent back to back, the later one is what remains.

      • setMinimizeToTray: (enabled: boolean) => Promise<TraySetMinimizeToTrayResponse>

        Hide to the tray instead of the taskbar when the window is minimized.

      • setTooltip: (tooltip: string) => Promise<TraySetTooltipResponse>

        Update the hover tooltip (max 128 characters).

      • showBalloon: (
            opts: {
                icon?: "error" | "info" | "warning";
                message: string;
                title: string;
            },
        ) => Promise<TrayShowBalloonResponse>

        Show a balloon notification. icon is 'info' (default) / 'warning' / 'error'.

    • ui: {
          blur: () => Promise<WindowBlurResponse>;
          broadcast: (message: JsonValue) => Promise<WindowBroadcastResponse>;
          cancelClose: () => Promise<WindowCancelCloseResponse>;
          center: () => Promise<WindowCenterResponse>;
          clearClickThroughExcludeRegions: (
              windowId?: string,
          ) => Promise<WindowClearClickThroughExcludeRegionsResponse>;
          clearDragRegions: () => Promise<WindowClearDragRegionsResponse>;
          clearNoDragRegions: () => Promise<WindowClearNoDragRegionsResponse>;
          close: () => Promise<WindowCloseResponse>;
          closeAllPopups: () => Promise<WindowCloseAllPopupsResponse>;
          closePopup: (windowId: string) => Promise<WindowClosePopupResponse>;
          confirmClose: () => Promise<WindowConfirmCloseResponse>;
          createPopup: (
              opts: WindowCreatePopupOptions,
          ) => Promise<WindowCreatePopupResponse>;
          enterFullscreen: (
              windowId?: string,
          ) => Promise<WindowEnterFullscreenResponse>;
          exitFullscreen: (
              windowId?: string,
          ) => Promise<WindowExitFullscreenResponse>;
          flash: (opts: WindowFlashParams) => Promise<WindowFlashResponse>;
          flashTaskbar: (count?: number) => Promise<WindowFlashTaskbarResponse>;
          focus: (windowId?: string) => Promise<WindowFocusResponse>;
          getAllWindows: () => Promise<WindowListResponse>;
          getBackdropPolicy: (
              windowId?: string,
          ) => Promise<WindowGetBackdropPolicyResponse>;
          getBounds: () => Promise<WindowGetBoundsResponse>;
          getCaptionButtonsWidth: () => Promise<WindowGetCaptionButtonsWidthResponse>;
          getCornerPreference: () => Promise<WindowGetCornerPreferenceResponse>;
          getCurrentWindowId: () => Promise<WindowGetCurrentWindowIdResponse>;
          getDevServerConfig: () => Promise<WindowGetDevServerConfigResponse>;
          getDpiScale: () => Promise<WindowGetDpiScaleResponse>;
          getMaxSize: (windowId?: string) => Promise<WindowGetMaxSizeResponse>;
          getMinSize: (windowId?: string) => Promise<WindowGetMinSizeResponse>;
          getMode: () => Promise<WindowGetModeResponse>;
          getPopupBehavior: (
              windowId?: string,
          ) => Promise<WindowGetPopupBehaviorResponse>;
          getState: () => Promise<WindowGetStateResponse>;
          getTitle: () => Promise<WindowGetTitleResponse>;
          getTitlebarHeight: () => Promise<WindowGetTitlebarHeightResponse>;
          getTitlebarInfo: () => Promise<WindowGetTitlebarInfoResponse>;
          getZoom: () => Promise<WindowGetZoomResponse>;
          hasSavedBounds: () => Promise<WindowHasSavedBoundsResponse>;
          isAlwaysOnTop: () => Promise<WindowIsAlwaysOnTopResponse>;
          isClickThrough: (
              windowId?: string,
          ) => Promise<WindowIsClickThroughResponse>;
          isFullscreen: (windowId?: string) => Promise<WindowIsFullscreenResponse>;
          isMaximized: () => Promise<WindowIsMaximizedResponse>;
          isMinimized: () => Promise<WindowIsMinimizedResponse>;
          isResizable: (windowId?: string) => Promise<WindowIsResizableResponse>;
          maximize: () => Promise<WindowMaximizeResponse>;
          minimize: () => Promise<WindowMinimizeResponse>;
          refreshWebView: () => Promise<WindowRefreshWebViewResponse>;
          reload: () => Promise<WindowReloadResponse>;
          resetZoom: () => Promise<WindowResetZoomResponse>;
          restore: () => Promise<WindowRestoreResponse>;
          sendMessage: (
              targetWindowId: string,
              message: JsonValue,
          ) => Promise<WindowSendMessageResponse>;
          setAcrylic: (
              opts: WindowSetAcrylicParams,
          ) => Promise<WindowSetAcrylicResponse>;
          setAlwaysOnTop: (enabled: boolean) => Promise<WindowSetAlwaysOnTopResponse>;
          setBackdropPolicy: (
              __namedParameters: WindowBackdropPolicyPatch & { windowId?: string },
          ) => Promise<WindowSetBackdropPolicyResponse>;
          setBackgroundTransparency: (
              opts: WindowSetBackgroundTransparencyParams,
          ) => Promise<WindowSetBackgroundTransparencyResponse>;
          setBlur: (opts: WindowSetBlurParams) => Promise<WindowSetBlurResponse>;
          setBounds: (
              __namedParameters: WindowSetBoundsParams,
          ) => Promise<WindowSetBoundsResponse>;
          setClickThrough: (
              opts: WindowSetClickThroughParams,
          ) => Promise<WindowSetClickThroughResponse>;
          setClickThroughExcludeRegions: (
              opts: WindowSetClickThroughExcludeRegionsParams,
          ) => Promise<WindowSetClickThroughExcludeRegionsResponse>;
          setCornerPreference: (
              mode: string,
          ) => Promise<WindowSetCornerPreferenceResponse>;
          setDarkMode: (
              enabled: boolean,
              windowId?: string,
          ) => Promise<WindowSetDarkModeResponse>;
          setDevServerConfig: (
              opts: WindowSetDevServerConfigParams,
          ) => Promise<WindowSetDevServerConfigResponse>;
          setDragRegions: (
              regions: WindowRegion[],
          ) => Promise<WindowSetDragRegionsResponse>;
          setFrameless: (
              frameless: boolean,
              windowId?: string,
          ) => Promise<WindowSetFramelessResponse>;
          setFullscreen: (
              enabled: boolean,
              windowId?: string,
          ) => Promise<WindowSetFullscreenResponse>;
          setMaximizeButtonRegion: (
              region?: WindowRegion,
          ) => Promise<WindowSetMaximizeButtonRegionResponse>;
          setMaxSize: (
              width: number,
              height: number,
              windowId?: string,
          ) => Promise<WindowSetMaxSizeResponse>;
          setMica: (opts?: WindowSetMicaParams) => Promise<WindowSetMicaResponse>;
          setMicaEffect: (
              opts?: WindowSetMicaEffectParams,
          ) => Promise<WindowSetMicaEffectResponse>;
          setMinSize: (
              width: number,
              height: number,
              windowId?: string,
          ) => Promise<WindowSetMinSizeResponse>;
          setNoDragRegions: (
              regions: WindowRegion[],
          ) => Promise<WindowSetNoDragRegionsResponse>;
          setPopupBehavior: (
              opts: WindowSetPopupBehaviorOptions,
          ) => Promise<WindowSetPopupBehaviorResponse>;
          setPosition: (x: number, y: number) => Promise<WindowSetPositionResponse>;
          setResizable: (
              resizable: boolean,
              windowId?: string,
          ) => Promise<WindowSetResizableResponse>;
          setSize: (width: number, height: number) => Promise<WindowSetSizeResponse>;
          setTitle: (title: string) => Promise<WindowSetTitleResponse>;
          setTitlebarHeight: (
              height: number,
          ) => Promise<WindowSetTitlebarHeightResponse>;
          setZoom: (zoom: number) => Promise<WindowSetZoomResponse>;
          setZoomForDpi: (dpi?: number) => Promise<WindowSetZoomForDpiResponse>;
          showContextMenu: (
              x?: number,
              y?: number,
          ) => Promise<UiShowContextMenuResponse>;
          showSystemMenu: (
              x: number,
              y: number,
              w?: number,
              h?: number,
          ) => Promise<WindowShowSystemMenuResponse>;
          startDrag: () => Promise<WindowStartDragResponse>;
          startResize: (edge: string) => Promise<WindowStartResizeResponse>;
          toggleAlwaysOnTop: () => Promise<WindowToggleAlwaysOnTopResponse>;
          toggleFullscreen: (
              windowId?: string,
          ) => Promise<WindowToggleFullscreenResponse>;
          toggleMaximize: () => Promise<WindowToggleMaximizeResponse>;
      }

      ui — window-management namespace.

    • unwrap: {
          <R extends { success: boolean }>(response: R): Extract<R>;
          <R extends { success: boolean }, K extends string | number | symbol>(
              response: R,
              key: K,
          ): Extract<R, { success: true }>[K];
      }
    • utils: {
          echo: (message: string) => Promise<TestEchoResponse>;
          formatTitle: (
              pattern: string,
              path?: string,
          ) => Promise<TitleformatEvalResponse>;
          getFileInfo: (path: string) => Promise<MetadataReadResponse>;
          ping: () => Promise<TestPingResponse>;
      }

      utils — diagnostic / glue helpers.

      formatTitle / getFileInfo are intentional façades over titleformat.eval / metadata.read respectively.

      • echo: (message: string) => Promise<TestEchoResponse>

        Round trip through test.echo; the message comes back as echo.

      • formatTitle: (pattern: string, path?: string) => Promise<TitleformatEvalResponse>

        Façade over titleformat.eval; an omitted or empty path evaluates the playing track.

      • getFileInfo: (path: string) => Promise<MetadataReadResponse>

        Façade over metadata.read.

      • ping: () => Promise<TestPingResponse>

        Round trip through test.ping; timestamp is the host's Unix time in seconds.

    • webview: { getSource: () => Promise<WebviewGetSourceResponse> }

      webview — facts about the calling WebView itself.

      • getSource: () => Promise<WebviewGetSourceResponse>

        Report where the host loaded this page from: the development server, a URL, a template folder, or the built-in "Frontend not found" page. The answer is the record the host made when it submitted the navigation; only activeTemplateName is read at the time of the call.