UNPKG

voicemeeter-connector

Version:
1 lines 29.1 kB
{"version":3,"file":"index.modern.mjs","sources":["../src/lib/constants.ts","../src/lib/dll-handler.ts","../src/lib/voicemeeter-connector.ts","../src/index.ts"],"sourcesContent":["export const InterfaceTypes = {\r\n strip: 0,\r\n bus: 1,\r\n};\r\n\r\nexport enum StripProperties {\r\n Mono = \"Mono\",\r\n Mute = \"Mute\",\r\n Solo = \"Solo\",\r\n MC = \"MC\",\r\n Gain = \"Gain\",\r\n Pan_x = \"Pan_x\",\r\n Pan_y = \"Pan_y\",\r\n Color_x = \"Color_x\",\r\n Color_y = \"Color_y\",\r\n fx_x = \"fx_x\",\r\n fx_y = \"fx_y\",\r\n Audibility = \"Audibility\",\r\n Comp = \"Comp\",\r\n Gate = \"Gate\",\r\n EqGain1 = \"EqGain1\",\r\n EqGain2 = \"EqGain2\",\r\n EqGain3 = \"EqGain3\",\r\n Label = \"Label\",\r\n A1 = \"A1\",\r\n A2 = \"A2\",\r\n A3 = \"A3\",\r\n A4 = \"A4\",\r\n A5 = \"A5\",\r\n B1 = \"B1\",\r\n B2 = \"B2\",\r\n B3 = \"B3\",\r\n FadeTo = \"FadeTo\",\r\n}\r\nexport enum BusProperties {\r\n Mono = \"Mono\",\r\n Mute = \"Mute\",\r\n EQ = \"EQ.on\",\r\n Gain = \"Gain\",\r\n NormalMode = \"mode.normal\",\r\n AmixMode = \"mode.Amix\",\r\n BmixMode = \"mode.Bmix\",\r\n RepeatMode = \"mode.Repeat\",\r\n CompositeMode = \"mode.Composite\",\r\n FadeTo = \"FadeTo\",\r\n Label = \"Label\",\r\n}\r\n\r\nexport enum MacroButtonModes {\r\n DEFAULT = 0x00_00_00_00,\r\n STATEONLY = 0x00_00_00_02,\r\n TRIGGER = 0x00_00_00_03,\r\n COLOR = 0x00_00_00_04,\r\n}\r\n","import Registry from \"winreg\";\r\n\r\nconst DLLHandler = {\r\n getDLLPath: async (): Promise<any> => {\r\n const regKey = new Registry({\r\n hive: Registry.HKLM,\r\n key: String.raw`\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}`,\r\n });\r\n return new Promise((resolve) => {\r\n regKey.values((err: any, items: any) => {\r\n if (err) {\r\n throw new Error(err);\r\n }\r\n const unistallerPath = items.find((i: any) => i.name === \"UninstallString\").value;\r\n const fileNameIndex = unistallerPath.lastIndexOf(\"\\\\\");\r\n resolve(unistallerPath.slice(0, fileNameIndex));\r\n });\r\n });\r\n },\r\n};\r\n\r\nexport default DLLHandler;\r\n","/* eslint-disable no-control-regex */\r\nimport koffi from \"koffi\";\r\n\r\nimport { Device, VMLibrary, VoiceMeeterTypes } from \"../types/voicemeeter-types\";\r\nimport { BusProperties, MacroButtonModes, StripProperties } from \"./constants\";\r\nimport DLLHandler from \"./dll-handler\";\r\n\r\n/**\r\n * @ignore\r\n */\r\nlet libVM: VMLibrary;\r\n/**\r\n * @ignore\r\n */\r\nlet instance: Voicemeeter;\r\n\r\nexport default class Voicemeeter {\r\n /**\r\n * Initializes the voice meeter dll connection.\r\n * This call is neccessary to use the api. It returns a promise with a VoiceMeeter instance\r\n */\r\n static init = async (): Promise<Voicemeeter> => {\r\n const dllPath = await DLLHandler.getDLLPath();\r\n\r\n return new Promise((resolve: (instance: Voicemeeter) => any) => {\r\n if (!instance) {\r\n instance = new Voicemeeter();\r\n }\r\n const lib = koffi.load(`${dllPath}/VoicemeeterRemote64.dll`);\r\n libVM = {\r\n VBVMR_Login: lib.func(\"long __stdcall VBVMR_Login(void)\"),\r\n VBVMR_Logout: lib.func(\"long __stdcall VBVMR_Logout(void)\"),\r\n VBVMR_RunVoicemeeter: lib.func(\"long __stdcall VBVMR_RunVoicemeeter(long mode)\"),\r\n VBVMR_IsParametersDirty: lib.func(\"long __stdcall VBVMR_IsParametersDirty(void)\"),\r\n VBVMR_GetLevel: lib.func(\"long __stdcall VBVMR_GetLevel(long type, long channel, _Out_ float* value)\"),\r\n VBVMR_GetParameterFloat: lib.func(\"long __stdcall VBVMR_GetParameterFloat(const char* param, _Out_ float* value)\"),\r\n VBVMR_GetParameterStringA: lib.func(\"long __stdcall VBVMR_GetParameterStringA(const char* param, _Out_ char* value)\"),\r\n VBVMR_SetParameters: lib.func(\"long __stdcall VBVMR_SetParameters(const char* param)\"),\r\n VBVMR_Output_GetDeviceNumber: lib.func(\"long __stdcall VBVMR_Output_GetDeviceNumber(void)\"),\r\n VBVMR_Output_GetDeviceDescA: lib.func(\r\n \"long __stdcall VBVMR_Output_GetDeviceDescA(long index, _Out_ long* type, _Out_ char* name, _Out_ char* hardwareId)\"\r\n ),\r\n VBVMR_Input_GetDeviceNumber: lib.func(\"long __stdcall VBVMR_Input_GetDeviceNumber(void)\"),\r\n VBVMR_Input_GetDeviceDescA: lib.func(\r\n \"long __stdcall VBVMR_Input_GetDeviceDescA(long index, long* type, char* name, char* hardwareId)\"\r\n ),\r\n VBVMR_GetVoicemeeterType: lib.func(\"long __stdcall VBVMR_GetVoicemeeterType(_Out_ long* type)\"),\r\n VBVMR_GetVoicemeeterVersion: lib.func(\"long __stdcall VBVMR_GetVoicemeeterVersion(_Out_ long* version)\"),\r\n VBVMR_MacroButton_IsDirty: lib.func(\"long __stdcall VBVMR_MacroButton_IsDirty(void)\"),\r\n VBVMR_MacroButton_GetStatus: lib.func(\r\n \"long __stdcall VBVMR_MacroButton_GetStatus(long nuLogicalButton, _Out_ float* pValue, long bitmode)\"\r\n ),\r\n VBVMR_MacroButton_SetStatus: lib.func(\r\n \"long __stdcall VBVMR_MacroButton_SetStatus(long nuLogicalButton, float fValue, long bitmode)\"\r\n ),\r\n };\r\n\r\n instance.isInitialised = true;\r\n resolve(instance);\r\n });\r\n };\r\n\r\n private isInitialised = false;\r\n private isConnected = false;\r\n private outputDevices: Device[] = [];\r\n private inputDevices: Device[] = [];\r\n private version = \"\";\r\n private type: VoiceMeeterTypes;\r\n private eventPool = [] as Array<() => void>;\r\n private stringParameters = [\"Label\", \"FadeTo\", \"FadeBy\", \"AppGain\", \"AppMute\", \"name\", \"ip\"];\r\n private timerInterval: NodeJS.Timeout;\r\n\r\n /**\r\n * Starts a connection to VoiceMeeter\r\n */\r\n public connect = (): { success: boolean; message: string; code: number } | never => {\r\n if (!this.isInitialised) {\r\n throw new Error(\"Await the initialisation before connect\");\r\n }\r\n if (this.isConnected) {\r\n // If already connected, still return success status instead of throwing\r\n return { success: true, message: \"Already connected.\", code: 0 };\r\n }\r\n\r\n const loginResult = libVM.VBVMR_Login();\r\n\r\n switch (loginResult) {\r\n case 0: {\r\n // Complete success, Voicemeeter is running\r\n this.isConnected = true;\r\n this.type = this.getVoicemeeterType();\r\n this.version = this.getVoicemeeterVersion();\r\n this.timerInterval = setInterval(this.checkPropertyChange, 10);\r\n return { success: true, message: \"Successfully connected to VoiceMeeter (VM Running).\", code: 0 };\r\n }\r\n case 1: {\r\n // Connected successfully but Voicemeeter application is not running\r\n // Pipe is established, can wait for VM to start\r\n this.isConnected = true;\r\n this.type = undefined;\r\n this.version = \"Unknown\";\r\n this.timerInterval = setInterval(this.checkPropertyChange, 10);\r\n return { success: true, message: \"Connected to VoiceMeeter API (VM App Not Running).\", code: 1 };\r\n }\r\n case -1: {\r\n // Failed to get client (unexpected error) - throw error\r\n this.isConnected = false;\r\n throw new Error(\"VoiceMeeter connection failed: Unable to get client (Unexpected error -1).\");\r\n }\r\n case -2: {\r\n // Unexpected login (logout should have been executed first) - throw error\r\n this.isConnected = false;\r\n throw new Error(\"VoiceMeeter connection failed: Unexpected login (Expected logout first -2).\");\r\n }\r\n default: {\r\n // Unknown return value - throw error\r\n this.isConnected = false;\r\n throw new Error(`VoiceMeeter connection failed with unknown error code: ${loginResult}.`);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Getter $outputDevices\r\n * @return {Device[] }\r\n */\r\n public get $outputDevices(): Device[] {\r\n return this.outputDevices;\r\n }\r\n\r\n /**\r\n * Getter $inputDevices\r\n * @return {Device[] }\r\n */\r\n public get $inputDevices(): Device[] {\r\n return this.inputDevices;\r\n }\r\n\r\n /**\r\n * Getter $version\r\n * @return {string }\r\n */\r\n public get $version(): string {\r\n return this.version;\r\n }\r\n\r\n /**\r\n * Getter $type\r\n * @return {VoiceMeeterTypes}\r\n */\r\n public get $type(): VoiceMeeterTypes {\r\n return this.type;\r\n }\r\n\r\n /**\r\n * Terminates the connection to VoiceMeeter\r\n */\r\n public disconnect = () => {\r\n if (!this.isConnected) {\r\n throw new Error(\"Not connected \");\r\n }\r\n try {\r\n if (libVM.VBVMR_Logout() === 0) {\r\n clearInterval(this.timerInterval);\r\n this.isConnected = false;\r\n return;\r\n }\r\n throw new Error(\"Disconnect failed\");\r\n } catch {\r\n throw new Error(\"Disconnect failed\");\r\n }\r\n };\r\n\r\n /**\r\n * Updates all input and ouput devices\r\n */\r\n public updateDeviceList = () => {\r\n if (!this.isConnected) {\r\n throw new Error(\"Not connected \");\r\n }\r\n this.outputDevices = [];\r\n this.inputDevices = [];\r\n const outputDeviceNumber = libVM.VBVMR_Output_GetDeviceNumber();\r\n for (let i = 0; i < outputDeviceNumber; i++) {\r\n const hardwareIdPtr = Buffer.alloc(256);\r\n const namePtr = Buffer.alloc(256);\r\n const typePtr = [0];\r\n\r\n libVM.VBVMR_Output_GetDeviceDescA(i, typePtr, namePtr, hardwareIdPtr);\r\n this.outputDevices.push({\r\n name: namePtr.toString().replaceAll(/\\u0000+$/g, \"\"),\r\n hardwareId: hardwareIdPtr.toString().replaceAll(/\\u0000+$/g, \"\"),\r\n type: typePtr[0],\r\n });\r\n }\r\n\r\n const inputDeviceNumber = libVM.VBVMR_Input_GetDeviceNumber();\r\n for (let i = 0; i < inputDeviceNumber; i++) {\r\n const hardwareIdPtr = Buffer.alloc(256);\r\n const namePtr = Buffer.alloc(256);\r\n const typePtr = [0];\r\n\r\n libVM.VBVMR_Input_GetDeviceDescA(i, typePtr, namePtr, hardwareIdPtr);\r\n this.inputDevices.push({\r\n name: namePtr.toString().replaceAll(/\\u0000+$/g, \"\"),\r\n hardwareId: hardwareIdPtr.toString().replaceAll(/\\u0000+$/g, \"\"),\r\n type: typePtr[0],\r\n });\r\n }\r\n };\r\n\r\n /**\r\n * Returns wheter a parameter has been changed\r\n */\r\n public isParametersDirty = () => {\r\n return libVM.VBVMR_IsParametersDirty();\r\n };\r\n\r\n /**\r\n * Gets a bus parameter.\r\n * @param {number} index Index of the bus\r\n * @param {BusProperties} property Property which should be get\r\n */\r\n\r\n public getBusParameter = (index: number, property: BusProperties) => {\r\n return this.getParameter(\"Bus\", index, property);\r\n };\r\n\r\n /**\r\n * Gets a strip parameter\r\n * @param {number} index Index of the strip\r\n * @param {StripProperties} property Property which should be get\r\n */\r\n public getStripParameter = (index: number, property: StripProperties) => {\r\n return this.getParameter(\"Strip\", index, property);\r\n };\r\n\r\n /**\r\n * Sets a parameter of a strip.\r\n * @param {number} index Strip number\r\n * @param {StripProperties} property Propertyname which should be changed\r\n * @param {any} value Property value\r\n */\r\n public setStripParameter = (index: number, property: StripProperties, value: any) => {\r\n return this.setParameter(\"Strip\", index, property, value);\r\n };\r\n\r\n /**\r\n * Sets a parameter of a bus.\r\n * @param {number} index Bus number\r\n * @param {StripProperties} property Propertyname which should be changed\r\n * @param {any} value Property value\r\n */\r\n public setBusParameter = (index: number, property: BusProperties, value: any) => {\r\n return this.setParameter(\"Bus\", index, property, value);\r\n };\r\n\r\n /**\r\n * @param {()=>any} fn Function which should be called if something changes\r\n */\r\n public attachChangeEvent = (fn: () => any) => {\r\n this.eventPool.push(fn);\r\n };\r\n /**\r\n * @param parameterName Name of the parameter that should be get\r\n * @returns {any} Parameter value\r\n */\r\n public getOption = (parameterName: string) => {\r\n if (!this.isConnected) {\r\n throw new Error(\"Not correct connected \");\r\n }\r\n // Some parameters return string values and require some post-processing, this checks for those parameters\r\n if (this.stringParameters.some((str) => parameterName.includes(str))) {\r\n const strPtr = Buffer.alloc(512);\r\n libVM.VBVMR_GetParameterStringA(parameterName, strPtr);\r\n return [...String.fromCharCode.apply(null, strPtr)]\r\n .filter((e: string) => {\r\n return e !== \"\\0\";\r\n })\r\n .join(\"\");\r\n }\r\n const valuePtr = [0];\r\n libVM.VBVMR_GetParameterFloat(parameterName, valuePtr);\r\n return valuePtr[0];\r\n };\r\n /**\r\n * Sets an option.\r\n * @param {string} option Option to set\r\n */\r\n public setOption = (option: string) => {\r\n const script = Buffer.alloc(option.length + 1);\r\n script.fill(0).write(option);\r\n libVM.VBVMR_SetParameters(script);\r\n return new Promise((resolve) => {\r\n setTimeout(resolve, 200);\r\n });\r\n };\r\n\r\n /**\r\n * Checks if any macro button has unsaved changes\r\n */\r\n public isMacroButtonDirty = () => {\r\n return libVM.VBVMR_MacroButton_IsDirty();\r\n };\r\n\r\n /**\r\n * Gets the status of a specific macro button\r\n * @param {number} buttonIndex - The index of the macro button\r\n * @param {number} [bitmode=0] - Bit mode parameter (optional, defaults to MacroButtonModes.DEFAULT)\r\n * @returns {number} The current status value of the macro button\r\n * @throws {Error} Throws an error if failed to get the button status\r\n */\r\n public getMacroButtonStatus = (buttonIndex: number, bitmode: number = MacroButtonModes.DEFAULT): number => {\r\n const valuePtr = [0];\r\n const result = libVM.VBVMR_MacroButton_GetStatus(buttonIndex, valuePtr, bitmode);\r\n if (result === 0) {\r\n return valuePtr[0];\r\n }\r\n throw new Error(`Failed to get macro button ${buttonIndex} status`);\r\n };\r\n\r\n /**\r\n * Sets the status of a specific macro button\r\n * @param {number} buttonIndex - The index of the macro button\r\n * @param {number} value - The status value to set\r\n * @param {number} [bitmode=0] - Bit mode parameter (optional, defaults to MacroButtonModes.DEFAULT)\r\n * @throws {Error} Throws an error if failed to set the button status\r\n */\r\n public setMacroButtonStatus = (buttonIndex: number, value: number, bitmode: number = MacroButtonModes.DEFAULT): void => {\r\n const result = libVM.VBVMR_MacroButton_SetStatus(buttonIndex, value, bitmode);\r\n if (result !== 0) {\r\n throw new Error(`Failed to set macro button ${buttonIndex} status`);\r\n }\r\n };\r\n\r\n /**\r\n * Checks whether properties has been changed and calls all event listeners\r\n */\r\n private checkPropertyChange = () => {\r\n let hasChanges = false;\r\n\r\n if (this.isParametersDirty() === 1) {\r\n hasChanges = true;\r\n }\r\n\r\n if (this.isMacroButtonDirty() === 1) {\r\n hasChanges = true;\r\n }\r\n\r\n if (hasChanges) {\r\n for (const eventListener of this.eventPool) {\r\n eventListener();\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Gets installed voicemeeter type.\r\n * Means Voicemeeter(normal,banana,potato)\r\n */\r\n private getVoicemeeterType = (): VoiceMeeterTypes => {\r\n const typePtr = [0];\r\n if (libVM.VBVMR_GetVoicemeeterType(typePtr) !== 0) {\r\n throw new Error(\"running failed\");\r\n }\r\n\r\n switch (typePtr[0]) {\r\n case 1: {\r\n // Voicemeeter\r\n return \"voicemeeter\";\r\n }\r\n case 2: {\r\n // Voicemeeter Banana\r\n return \"voicemeeterBanana\";\r\n }\r\n case 3: {\r\n // Voicemeeter Potato\r\n return \"voicemeeterPotato\";\r\n }\r\n default: {\r\n throw new Error(\"Voicemeeter seems not to be installed\");\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Returns the installed voicemeeter version\r\n */\r\n private getVoicemeeterVersion = () => {\r\n const versionPtr = [0];\r\n if (libVM.VBVMR_GetVoicemeeterVersion(versionPtr) !== 0) {\r\n throw new Error(\"running failed\");\r\n }\r\n // For info on this see: https://github.com/mirror/equalizerapo/blob/53d885f7f1a097b457e17a5206b7d60f647877a8/VoicemeeterClient/VoicemeeterRemote.h#L122-L135\r\n const version =\r\n `${(versionPtr[0] & 0xff_00_00_00) >> 24}` +\r\n `.${(versionPtr[0] & 0x00_ff_00_00) >> 16}` +\r\n `.${(versionPtr[0] & 0x00_00_ff_00) >> 8}` +\r\n `.${versionPtr[0] & 0x00_00_00_ff}`;\r\n return version;\r\n };\r\n\r\n /**\r\n * Gets a parameter of voicemeeter\r\n * @param {'Strip'|'Bus'} selector Strip or Bus\r\n * @param {number} index Number of strip or bus\r\n * @param {StripProperties|BusProperties} property Property which should be read\r\n */\r\n private getParameter = (selector: \"Strip\" | \"Bus\", index: number, property: StripProperties | BusProperties) => {\r\n const parameterName = `${selector}[${index}].${property}`;\r\n return this.getOption(parameterName);\r\n };\r\n\r\n /**\r\n * Sets a parameter of a bus or Strip\r\n * @param {'Strip'|'Bus'} selector\r\n * @param {number} index Number of strip or bus\r\n * @param {StripProperties|BusProperties} property Propertyname which should be changed\r\n * @param {any} value Property value\r\n */\r\n private setParameter = (\r\n selector: \"Strip\" | \"Bus\",\r\n index: number,\r\n property: StripProperties | BusProperties,\r\n value: any\r\n ): Promise<any> => {\r\n if (!this.isConnected) {\r\n throw new Error(\"Not connected \");\r\n }\r\n const scriptString = `${selector}[${index}].${property}=${value};`;\r\n return this.setOption(scriptString);\r\n };\r\n /**\r\n * Gets realtime audio level see the VoicemeeterRemote API: [VoicemeeterRemote.h GetLevel](https://github.com/mirror/equalizerapo/blob/7aece1b788fce5aa11873f3842a0d01f7c78454b/VoicemeeterClient/VoicemeeterRemote.h#L284),\r\n * for more details about the parameters\r\n * @param {0|1|2|3} type 0 = pre fader input levels. 1 = post fader input levels. 2= post Mute input levels. 3= output levels\r\n * @param channel audio channel zero based index\r\n * @returns {float} Current audio level\r\n */\r\n public getLevel = (type: 0 | 1 | 2 | 3, channel: number) => {\r\n const levelPtr = [0];\r\n libVM.VBVMR_GetLevel(type, channel, levelPtr);\r\n return levelPtr[0];\r\n };\r\n}\r\n","import * as constants from \"./lib/constants\";\r\n\r\nconst { BusProperties, InterfaceTypes, StripProperties, MacroButtonModes } = constants;\r\n\r\nexport { BusProperties, InterfaceTypes, MacroButtonModes, StripProperties };\r\n\r\nexport { default as Voicemeeter } from \"./lib/voicemeeter-connector\";\r\nexport * as types from \"./types/voicemeeter-types\";\r\n"],"names":["StripProperties","BusProperties","MacroButtonModes","strip","bus","_t","_","t","libVM","instance","Voicemeeter","constructor","isInitialised","isConnected","this","outputDevices","inputDevices","version","type","eventPool","stringParameters","timerInterval","connect","Error","success","message","code","loginResult","VBVMR_Login","getVoicemeeterType","getVoicemeeterVersion","setInterval","checkPropertyChange","undefined","disconnect","VBVMR_Logout","clearInterval","_unused","updateDeviceList","outputDeviceNumber","VBVMR_Output_GetDeviceNumber","i","hardwareIdPtr","Buffer","alloc","namePtr","typePtr","VBVMR_Output_GetDeviceDescA","push","name","toString","replaceAll","hardwareId","inputDeviceNumber","VBVMR_Input_GetDeviceNumber","VBVMR_Input_GetDeviceDescA","isParametersDirty","VBVMR_IsParametersDirty","getBusParameter","index","property","getParameter","getStripParameter","setStripParameter","value","setParameter","setBusParameter","attachChangeEvent","fn","getOption","parameterName","some","str","includes","strPtr","VBVMR_GetParameterStringA","String","fromCharCode","apply","filter","e","join","valuePtr","VBVMR_GetParameterFloat","setOption","option","script","length","fill","write","VBVMR_SetParameters","Promise","resolve","setTimeout","isMacroButtonDirty","VBVMR_MacroButton_IsDirty","getMacroButtonStatus","buttonIndex","bitmode","DEFAULT","VBVMR_MacroButton_GetStatus","setMacroButtonStatus","VBVMR_MacroButton_SetStatus","hasChanges","eventListener","VBVMR_GetVoicemeeterType","versionPtr","VBVMR_GetVoicemeeterVersion","selector","getLevel","channel","levelPtr","VBVMR_GetLevel","$outputDevices","$inputDevices","$version","$type","init","async","dllPath","regKey","Registry","hive","HKLM","key","raw","values","err","items","unistallerPath","find","fileNameIndex","lastIndexOf","slice","DLLHandler","lib","koffi","load","func","VBVMR_RunVoicemeeter","InterfaceTypes","constants"],"mappings":"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"}