{"version":3,"file":"audio-host.mjs","names":[],"sources":["../../src/hosts/audio-host.ts"],"sourcesContent":["/* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD */\n/* SPDX-License-Identifier: Apache-2.0 */\n\n/**\n * In-memory BrookesiaHost for AudioPlayback — Node/vitest only, not used on device.\n * Import: `@brookesia/service/hosts/audio`\n */\n\nimport type { BrookesiaHost } from '../common/brookesia-host.ts';\nimport { serializeRpcError, serializeRpcResult } from '../common/rpc-json.ts';\nimport { AUDIO_PLAYBACK_FUNCTIONS, AUDIO_PLAYBACK_SERVICE_NAME } from '../audio/audio-client.ts';\nimport type { AudioPlayState } from '../audio/audio-types.ts';\n\ntype AudioMockState = {\n  volume: number;\n  mute: boolean;\n  playState: AudioPlayState;\n  currentUrl: string;\n  currentUrls: string[];\n};\n\nlet nextHandle = 1;\nconst handles = new Map<number, AudioMockState>();\n\nfunction defaultState(): AudioMockState {\n  return {\n    volume: 80,\n    mute: false,\n    playState: 'Idle',\n    currentUrl: '',\n    currentUrls: [],\n  };\n}\n\nfunction getState(handle: number): AudioMockState {\n  const state = handles.get(handle);\n  if (!state) {\n    throw new Error(`AudioPlayback memory host: invalid handle ${handle}`);\n  }\n  return state;\n}\n\nexport type AudioHostOptions = {\n  volume?: number;\n  mute?: boolean;\n};\n\nexport function createAudioHost(options?: AudioHostOptions): BrookesiaHost {\n  return {\n    service_available(name: string): boolean {\n      return name === AUDIO_PLAYBACK_SERVICE_NAME;\n    },\n\n    start_service(name: string): number {\n      if (name !== AUDIO_PLAYBACK_SERVICE_NAME) {\n        throw new Error(`AudioPlayback memory host: unknown service ${name}`);\n      }\n      const handle = nextHandle++;\n      handles.set(handle, {\n        ...defaultState(),\n        volume: options?.volume ?? 80,\n        mute: options?.mute ?? false,\n      });\n      return handle;\n    },\n\n    stop_service(handle: number): void {\n      handles.delete(handle);\n    },\n\n    call_function(handle: number, functionName: string, paramsJson: string): string {\n      const state = getState(handle);\n      const params = JSON.parse(paramsJson) as Record<string, unknown>;\n\n      try {\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.Play) {\n          state.currentUrl = String(params.Url ?? '');\n          state.currentUrls = [state.currentUrl];\n          state.playState = 'Playing';\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.PlayUrls) {\n          const urls = (params.Urls as string[]) ?? [];\n          state.currentUrls = [...urls];\n          state.currentUrl = urls[0] ?? '';\n          state.playState = urls.length > 0 ? 'Playing' : 'Idle';\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.Pause) {\n          if (state.playState === 'Playing') {\n            state.playState = 'Paused';\n          }\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.Resume) {\n          if (state.playState === 'Paused') {\n            state.playState = 'Playing';\n          }\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.Stop) {\n          state.playState = 'Idle';\n          state.currentUrl = '';\n          state.currentUrls = [];\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.SetVolume) {\n          state.volume = Number(params.Volume ?? 0);\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.GetVolume) {\n          return serializeRpcResult(state.volume);\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.SetMute) {\n          state.mute = Boolean(params.Enable);\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.GetMute) {\n          return serializeRpcResult(state.mute);\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.LoadData) {\n          return serializeRpcResult();\n        }\n\n        if (functionName === AUDIO_PLAYBACK_FUNCTIONS.ResetData) {\n          Object.assign(state, defaultState());\n          return serializeRpcResult();\n        }\n\n        return serializeRpcError(`unknown function ${functionName}`);\n      } catch (err) {\n        const message = err instanceof Error ? err.message : String(err);\n        return serializeRpcError(message);\n      }\n    },\n  };\n}\n\nexport function resetAudioHostState(): void {\n  handles.clear();\n  nextHandle = 1;\n}\n"],"mappings":";;;AAqBA,IAAI,aAAa;AACjB,MAAM,0BAAU,IAAI,IAA4B;AAEhD,SAAS,eAA+B;CACtC,OAAO;EACL,QAAQ;EACR,MAAM;EACN,WAAW;EACX,YAAY;EACZ,aAAa,CAAC;CAChB;AACF;AAEA,SAAS,SAAS,QAAgC;CAChD,MAAM,QAAQ,QAAQ,IAAI,MAAM;CAChC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,6CAA6C,QAAQ;CAEvE,OAAO;AACT;AAOA,SAAgB,gBAAgB,SAA2C;CACzE,OAAO;EACL,kBAAkB,MAAuB;GACvC,OAAO,SAAS;EAClB;EAEA,cAAc,MAAsB;GAClC,IAAI,SAAA,iBACF,MAAM,IAAI,MAAM,8CAA8C,MAAM;GAEtE,MAAM,SAAS;GACf,QAAQ,IAAI,QAAQ;IAClB,GAAG,aAAa;IAChB,QAAQ,SAAS,UAAU;IAC3B,MAAM,SAAS,QAAQ;GACzB,CAAC;GACD,OAAO;EACT;EAEA,aAAa,QAAsB;GACjC,QAAQ,OAAO,MAAM;EACvB;EAEA,cAAc,QAAgB,cAAsB,YAA4B;GAC9E,MAAM,QAAQ,SAAS,MAAM;GAC7B,MAAM,SAAS,KAAK,MAAM,UAAU;GAEpC,IAAI;IACF,IAAI,iBAAiB,yBAAyB,MAAM;KAClD,MAAM,aAAa,OAAO,OAAO,OAAO,EAAE;KAC1C,MAAM,cAAc,CAAC,MAAM,UAAU;KACrC,MAAM,YAAY;KAClB,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,UAAU;KACtD,MAAM,OAAQ,OAAO,QAAqB,CAAC;KAC3C,MAAM,cAAc,CAAC,GAAG,IAAI;KAC5B,MAAM,aAAa,KAAK,MAAM;KAC9B,MAAM,YAAY,KAAK,SAAS,IAAI,YAAY;KAChD,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,OAAO;KACnD,IAAI,MAAM,cAAc,WACtB,MAAM,YAAY;KAEpB,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,QAAQ;KACpD,IAAI,MAAM,cAAc,UACtB,MAAM,YAAY;KAEpB,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,MAAM;KAClD,MAAM,YAAY;KAClB,MAAM,aAAa;KACnB,MAAM,cAAc,CAAC;KACrB,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,WAAW;KACvD,MAAM,SAAS,OAAO,OAAO,UAAU,CAAC;KACxC,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,WAC5C,OAAO,mBAAmB,MAAM,MAAM;IAGxC,IAAI,iBAAiB,yBAAyB,SAAS;KACrD,MAAM,OAAO,QAAQ,OAAO,MAAM;KAClC,OAAO,mBAAmB;IAC5B;IAEA,IAAI,iBAAiB,yBAAyB,SAC5C,OAAO,mBAAmB,MAAM,IAAI;IAGtC,IAAI,iBAAiB,yBAAyB,UAC5C,OAAO,mBAAmB;IAG5B,IAAI,iBAAiB,yBAAyB,WAAW;KACvD,OAAO,OAAO,OAAO,aAAa,CAAC;KACnC,OAAO,mBAAmB;IAC5B;IAEA,OAAO,kBAAkB,oBAAoB,cAAc;GAC7D,SAAS,KAAK;IAEZ,OAAO,kBADS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAC/B;GAClC;EACF;CACF;AACF;AAEA,SAAgB,sBAA4B;CAC1C,QAAQ,MAAM;CACd,aAAa;AACf"}