commit 7805b14ff1e9845dbdab114f734dbb4d85c23006 Author: onyx-and-iris Date: Tue Jun 25 04:34:28 2024 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff55d68 --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +.vscode/ \ No newline at end of file diff --git a/include/VoicemeeterRemote.h b/include/VoicemeeterRemote.h new file mode 100644 index 0000000..f1481e1 --- /dev/null +++ b/include/VoicemeeterRemote.h @@ -0,0 +1,1093 @@ +/******************************************************************************/ +/* Voicemeeter Remote API. V.Burel©2015-2023 */ +/******************************************************************************/ +/* This Library allows communication with Voicemeeter applications */ +/* 4 Client Applications can be connected to remote Voicemeeter. */ +/* it also allows communication with MacroButtons application. */ +/******************************************************************************/ +/* */ +/* OFFICIAL LINK : WWW.VOICEMEETER.COM */ +/* */ +/******************************************************************************/ +/* COPYRIGHT: Vincent Burel(c)2015-2021 All Rights Reserved */ +/******************************************************************************/ +/* */ +/* LICENSING: VoicemeeterRemote.dll usage is driven by a license agreement */ +/* given in VoicemeeterRemoteAPI.pdf or readme.txt */ +/* */ +/******************************************************************************/ +/* long = 32 bit integer */ +/******************************************************************************/ + + +#ifndef __VOICEMEETER_REMOTE_H__ +#define __VOICEMEETER_REMOTE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define VBVMR_RESULT_OK 0 + +/******************************************************************************/ +/* */ +/* Login */ +/* */ +/******************************************************************************/ + +/** @name Communication Login / logout +* @{ */ + + /** + @brief Open Communication Pipe With Voicemeeter (typically called on software startup). + @return : 0: OK (no error). + 1: OK but Voicemeeter Application not launched. + -1: cannot get client (unexpected) + -2: unexpected login (logout was expected before). + */ + +long __stdcall VBVMR_Login(void); + + /** + @brief Close Communication Pipe With Voicemeeter (typically called on software end). + @return : 0 if ok. + */ + +long __stdcall VBVMR_Logout(void); + + + /** + @brief Run Voicemeeter Application (get installation directory and run Voicemeeter Application). + @param vType : Voicemeeter type (1 = Voicemeeter, 2= Voicemeeter Banana, 3= Voicemeeter Potato, 6 = Potato x64 bits). + @return : 0: Ok. + -1: not installed (UninstallString not found in registry). + -2: unknown vType number + */ + +long __stdcall VBVMR_RunVoicemeeter(long vType); + + +/** @} */ + + + + + + + + + + + +/******************************************************************************/ +/* */ +/* General Information */ +/* */ +/******************************************************************************/ + +/** @name General Information +* @{ */ + + /** + @brief Get Voicemeeter Type + @param pType : Pointer on 32bit long receiving the type (1 = Voicemeeter, 2= Voicemeeter Banana, 3 Potato). + + VOICEMEETER STRIP/BUS INDEX ASSIGNMENT + + | Strip 1 | Strip 2 |Virtual Input| BUS A | BUS B | + +---------+---------+-------------+---------+---------+ + | 0 | 1 | 2 | 0 | 1 | + + VOICEMEETER BANANA STRIP/BUS INDEX ASSIGNMENT + + | Strip 1 | Strip 2 | Strip 2 |Virtual Input|Virtual AUX|BUS A1|BUS A2|BUS A3|BUS B1|BUS B2| + +---------+---------+---------+-------------+-----------+------+------+------+------+------+ + | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 | + + VOICEMEETER POTATO STRIP/BUS INDEX ASSIGNMENT + + | Strip 1 | Strip 2 | Strip 2 | Strip 2 | Strip 2 |Virtual Input|Virtual AUX| VAIO3 |BUS A1|BUS A2|BUS A3|BUS A4|BUS A5|BUS B1|BUS B2|BUS B3| + +---------+---------+---------+---------+---------+-------------+-----------+-----------+------+------+------+------+------+------+------+------+ + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | + + + @return : 0: OK (no error). + -1: cannot get client (unexpected) + -2: no server. + */ + +long __stdcall VBVMR_GetVoicemeeterType(long * pType); + + /** + @brief Get Voicemeeter Version + @param pType : Pointer on 32bit integer receiving the version (v1.v2.v3.v4) + v1 = (version & 0xFF000000)>>24; + v2 = (version & 0x00FF0000)>>16; + v3 = (version & 0x0000FF00)>>8; + v4 = version & 0x000000FF; + + @return : 0: OK (no error). + -1: cannot get client (unexpected) + -2: no server. + */ + +long __stdcall VBVMR_GetVoicemeeterVersion(long * pVersion); + + +/** @} */ + + + + + + + + + + + + + + + + + + +/******************************************************************************/ +/* */ +/* Get parameters */ +/* */ +/******************************************************************************/ + +/** @name Getting Parameters +* @{ */ + + /** + @brief Check if parameters have changed. + Call this function periodically (typically every 10 or 20ms). + (this function must be called from one thread only) + + @return: 0: no new paramters. + 1: New parameters -> update your display. + -1: error (unexpected) + -2: no server. + */ + +long __stdcall VBVMR_IsParametersDirty(void); + + /** + @brief get parameter value. + @param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table) + @param pValue : Pointer on float (32bit float by reference) receiving the wanted value. + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + -5: structure mismatch + */ + +long __stdcall VBVMR_GetParameterFloat(char * szParamName, float * pValue); + + /** + @brief get parameter value. + @param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table) + @param pValue : Pointer on String (512 char or wchar) receiving the wanted value. + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + -5: structure mismatch + */ + +long __stdcall VBVMR_GetParameterStringA(char * szParamName, char * szString); +long __stdcall VBVMR_GetParameterStringW(char * szParamName, unsigned short * wszString); + +/** @} */ + + + + + + + + + +/******************************************************************************/ +/* */ +/* Get levels */ +/* */ +/******************************************************************************/ + +/** @name Getting RT Data +* @{ */ + + /** + @brief Get Current levels. + (this function must be called from one thread only) + + @param nType: 0= pre fader input levels. + 1= post fader input levels. + 2= post Mute input levels. + 3= output levels. + + @param nuChannel: audio channel zero based index + for input 0 = in#1 left, 1= in#1 Right, etc... + for output 0 = busA ch1, 1 = busA ch2... + + VOICEMEETER CHANNEL ASSIGNMENT + + | Strip 1 | Strip 2 | Virtual Input | + +----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | + + | Output A1 / A2 | Virtual Output | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | + + VOICEMEETER BANANA CHANNEL ASSIGNMENT + + | Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | + + | Output A1 | Output A2 | Output A3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | + + | Virtual Output B1 | Virtual Output B2 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + VOICEMEETER POTATO CHANNEL ASSIGNMENT + + | Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | VAIO3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | + + | Output A1 | Output A2 | Output A3 | Output A4 | Output A5 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + | Virtual Output B1 | Virtual Output B2 | Virtual Output B3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | + + + @return : 0: OK (no error). + -1: error + -2: no server. + -3: no level available + -4: out of range + */ + +long __stdcall VBVMR_GetLevel(long nType, long nuChannel, float * pValue); + + + /** + @brief Get MIDI message from M.I.D.I. input device used by Voicemeeter M.I.D.I. mapping. + (this function must be called from one thread only) + + @param pMIDIBuffer: pointer on MIDI Buffer. Expected message size is below 4 bytes, + but it's recommended to use 1024 Bytes local buffer to receive + possible multiple M.I.D.I. event message in optimal way: + unsigned char pBuffer[1024]; + + + @return : >0: number of bytes placed in buffer (2 or 3 byte for usual M.I.D.I. message) + -1: error + -2: no server. + -5: no MIDI data + -6: no MIDI data + */ + + +long __stdcall VBVMR_GetMidiMessage(unsigned char *pMIDIBuffer, long nbByteMax); + + + /** + @brief Send MIDI message to M.I.D.I. output device used by Voicemeeter M.I.D.I. mapping. + (this function must be called from one thread only) + + @param pMIDIBuffer: pointer on MIDI Buffer containing consistent MIDI message. + (we recommand to not use more than 4KB buffer); + + + @return : >0: number of bytes sent. + -1: error + -2: no server. + -5: cannot send MIDI data + */ + + +long __stdcall VBVMR_SendMidiMessage(unsigned char *pMIDIBuffer, long nbByte); + + +/** @} */ + + + + + + + + + + +/******************************************************************************/ +/* */ +/* Set Parameters */ +/* */ +/******************************************************************************/ + +/** @name Setting Parameters +* @{ */ + + /** + @brief Set a single float 32 bits parameters . + @param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table) + example: + Strip[1].gain + Strip[0].mute + Bus[0].gain + Bus[0].eq.channel[0].cell[0].gain + + @param pValue : float 32bit containing the new value. + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + */ + +long __stdcall VBVMR_SetParameterFloat(char * szParamName, float Value); + + + + /** + @brief Set a single string parameters . + @param szParamName : Null Terminal ASCII String giving the name of the parameter (see parameters name table) + example: + Strip[1].name + Strip[0].device.mme + Bus[0].device.asio + + @param szString : zero terminal string. + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + + */ + + +long __stdcall VBVMR_SetParameterStringA(char * szParamName, char * szString); +long __stdcall VBVMR_SetParameterStringW(char * szParamName, unsigned short * wszString); + + + + + /** + @brief Set one or several parameters by a script ( < 48 kB ). + @param szParamName : Null Terminal ASCII String giving the script + (script allows to change several parameters in the same time - SYNCHRO). + Possible Instuction separators: ',' ';' or '\n'(CR) + EXAMPLE: + "Strip[0].gain = -6.0 + Strip[0].A1 = 0 + Strip[0].B1 = 1 + Strip[1].gain = -6.0 + Strip[2].gain = 0.0 + Strip[3].name = "Skype Caller" " + + @return : 0: OK (no error). + >0: number of line causing script error. + -1: error + -2: no server. + -3: unexpected error + -4: unexpected error + */ + +long __stdcall VBVMR_SetParameters(char * szParamScript); +long __stdcall VBVMR_SetParametersW(unsigned short * szParamScript); + + +/** @} */ + + + + + + + + + + + +/******************************************************************************/ +/* DEVICES ENUMERATOR */ +/******************************************************************************/ + + +/** @name Device Enumeration Functions +* @{ */ + +#define VBVMR_DEVTYPE_MME 1 +#define VBVMR_DEVTYPE_WDM 3 +#define VBVMR_DEVTYPE_KS 4 +#define VBVMR_DEVTYPE_ASIO 5 + + /** + @brief Get number of Audio Output Device available on the system + @return : return number of device found. + */ + +long __stdcall VBVMR_Output_GetDeviceNumber(void); + + /** + @brief Return pointer on Output Device Descriptor according index + @param zindex : zero based index + @param nType : Pointer on 32bit long receiving the type (pointer can be NULL). + @param szName : Pointer on string (256 char min) receiving the device name (pointer can be NULL). + @param szHardwareId : Pointer on string (256 char min) receiving the hardware ID (pointer can be NULL). + @return : 0: OK (no error). + */ + +long __stdcall VBVMR_Output_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId); +long __stdcall VBVMR_Output_GetDeviceDescW(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId); + + /** + @brief Get number of Audio Input Device available on the system + @return : return number of device found. + */ + +long __stdcall VBVMR_Input_GetDeviceNumber(void); + + /** + @brief Return pointer on Input Device Descriptor according index + @param zindex : zero based index + @param nType : Pointer on 32bit long receiving the type (pointer can be NULL). + @param szName : Pointer on string (256 char min) receiving the device name (pointer can be NULL). + @param szHardwareId : Pointer on string (256 char min) receiving the hardware ID (pointer can be NULL). + @return : 0: OK (no error). + */ + +long __stdcall VBVMR_Input_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId); +long __stdcall VBVMR_Input_GetDeviceDescW(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId); + + + +/** @} */ + + + + + + +/******************************************************************************/ +/* VB-AUDIO CALLBACK */ +/******************************************************************************/ +/* 4x Functions to process all voicemeeter audio input and output channels */ +/* */ +/* VBVMR_AudioCallbackRegister :to register your audio callback(s) */ +/* VBVMR_AudioCallbackStart :to start the audio stream */ +/* VBVMR_AudioCallbackStop :to stop the audio stream */ +/* VBVMR_AudioCallbackUnregister :to unregister / Release callback(s) */ +/******************************************************************************/ + +/** @name VB-Audio Callback Functions +* @{ */ + + +typedef struct tagVBVMR_AUDIOINFO +{ + long samplerate; + long nbSamplePerFrame; +} VBVMR_T_AUDIOINFO, *VBVMR_PT_AUDIOINFO, *VBVMR_LPT_AUDIOINFO; + + +typedef struct tagVBVMR_AUDIOBUFFER +{ + long audiobuffer_sr; //Sampling Rate + long audiobuffer_nbs; //number of sample per frame + long audiobuffer_nbi; //number of inputs + long audiobuffer_nbo; //number of outputs + float * audiobuffer_r[128]; //nbi input pointers containing frame of nbs sample (of 32bits float) + float * audiobuffer_w[128]; //nbo output pointers containing frame of nbs sample (of 32bits float) +} VBVMR_T_AUDIOBUFFER, *VBVMR_PT_AUDIOBUFFER, *VBVMR_LPT_AUDIOBUFFER; + + + /** + @brief VB-AUDIO Callback is called for different task to Initialize, perform and end your process. + VB-AUDIO Callback is part of single TIME CRITICAL Thread. + VB-AUDIO Callback is non re-entrant (cannot be called while in process) + VB-AUDIO Callback is supposed to be REAL TIME when called to process buffer. + (it means that the process has to be performed as fast as possible, waiting cycles are forbidden. + do not use O/S synchronization object, even Critical_Section can generate waiting cycle. Do not use + system functions that can generate waiting cycle like display, disk or communication functions for example). + + @param lpUser: User pointer given on callback registration. + @param ncommand: reason why the callback is called. + @param lpData: pointer on structure, pending on nCommand. + @param nnn: additional data, unused + + @return : 0: always 0 (unused). + */ + + +typedef long (__stdcall *T_VBVMR_VBAUDIOCALLBACK)(void * lpUser, long nCommand, void * lpData, long nnn); + + +#define VBVMR_CBCOMMAND_STARTING 1 //command to initialize data according SR and buffer size + //info = (VBVMR_LPT_AUDIOINFO)lpData + +#define VBVMR_CBCOMMAND_ENDING 2 //command to release data +#define VBVMR_CBCOMMAND_CHANGE 3 //If change in audio stream, you will have to restart audio + +#define VBVMR_CBCOMMAND_BUFFER_IN 10 //input insert +#define VBVMR_CBCOMMAND_BUFFER_OUT 11 //bus output insert +#define VBVMR_CBCOMMAND_BUFFER_MAIN 20 //all i/o + //audiobuffer = (VBVMR_LPT_AUDIOBUFFER)lpData + //nnn = synchro = 1 if synchro with Voicemeeter + +/* + ----------------------------------------------------- + AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_IN + ----------------------------------------------------- + VOICEMEETER + + | Strip 1 | Strip 2 | Virtual Input | + +----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | + + VOICEMEETER BANANA + + | Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | + + VOICEMEETER 8 + + | Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | Virtual Input 8 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | + + +----------------------------------------------------- + AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_OUT +----------------------------------------------------- + VOICEMEETER + + | Output A1 / A2 | Virtual Output | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | + + VOICEMEETER BANANA + + | Output A1 | Output A2 | Output A3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | + + | Virtual Output B1 | Virtual Output B2 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + + VOICEMEETER 8 + + | Output A1 | Output A2 | Output A3 | Output A4 | Output A5 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + | Virtual Output B1 | Virtual Output B2 | Virtual Output B3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | + + +----------------------------------------------------- + AUDIO BUFFER for VBVMR_CBCOMMAND_BUFFER_MAIN +----------------------------------------------------- + VOICEMEETER + + | Strip 1 | Strip 2 | Virtual Input | + +----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | + + | Output A1 / A2 | Virtual Output | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | + Output buffer provides outputs only: + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | + + VOICEMEETER BANANA + + | Strip 1 | Strip 2 | Strip 3 | Virtual Input | Virtual Input AUX | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | + + | Output A1 | Output A2 | Output A3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | + Output buffer provides outputs only: + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | + + | Virtual Output B1 | Virtual Output B2 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | + Output buffer provides outputs only: + | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + + VOICEMEETER 8 + + | Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | Virtual Input 8 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | + + | Output A1 | Output A2 | Output A3 | Output A4 | Output A5 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | + Output buffer provides outputs only: + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | + + | Virtual Output B1 | Virtual Output B2 | Virtual Output B3 | + +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | + Output buffer provides outputs only: + | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | + + +*/ + + /** + @brief register your audio callback function to receive real time audio buffer + it's possible to register up to 3x different Audio Callback in the same application or in + 3x different applications. In the same application, this is possible because Voicemeeter + provides 3 kind of audio Streams: + - AUDIO INPUT INSERT (to process all Voicemeeter inputs as insert) + - AUDIO OUTPUT INSERT (to process all Voicemeeter BUS outputs as insert) + - ALL AUDIO I/O (to process all Voicemeeter i/o). + Note: a single callback can be used to receive the 3 possible audio streams. + + @param mode : callback type (main, input or bus output) see define below + @param pCallback : Pointer on your callback function. + @param lpUser : user pointer (pointer that will be passed in callback first argument). + @param szClientName[64]: IN: Name of the application registering the Callback. + OUT: Name of the application already registered. + @return : 0: OK (no error). + -1: error + 1: callback already registered (by another application). + */ + +long __stdcall VBVMR_AudioCallbackRegister(long mode, T_VBVMR_VBAUDIOCALLBACK pCallback, void * lpUser, char szClientName[64]); + +#define VBVMR_AUDIOCALLBACK_IN 0x00000001 //to process input insert +#define VBVMR_AUDIOCALLBACK_OUT 0x00000002 //to process output bus insert +#define VBVMR_AUDIOCALLBACK_MAIN 0x00000004 //to receive all i/o + + /** + @brief Start / Stop Audio processing + + he Callback will be called with + @return : 0: OK (no error). + -1: error + -2: no callback registred. + */ + +long __stdcall VBVMR_AudioCallbackStart(void); +long __stdcall VBVMR_AudioCallbackStop(void); + + + /** + @brief unregister your callback to release voicemeeter virtual driver + (this function will automatically call VBVMR_AudioCallbackStop() function) + @param pCallback : Pointer on your callback function. + @return : 0: OK (no error). + -1: error + 1: callback already unregistered. + */ + +long __stdcall VBVMR_AudioCallbackUnregister(void); + + + +/** @} */ + + + + + + +/******************************************************************************/ +/* */ +/* Macro Buttons */ +/* */ +/******************************************************************************/ + +/** @name Macro Buttons functions +* @{ */ + + /** + @brief Check if Macro Buttons states changed. + Call this function periodically (typically every 50 or 500ms) to know if something happen on MacroButton states . + (this function must be called from one thread only) + + @return: 0: no new status. + >0: last nu logical button status changed. + -1: error (unexpected) + -2: no server. + */ + +long __stdcall VBVMR_MacroButton_IsDirty(void); + + /** + @brief get current status of a given button. + @param nuLogicalButton : button index: 0 to 79) + @param pValue : Pointer on float (32bit float by reference) receiving the wanted value (0.0 = OFF / 1.0 = ON). + @param bitmode: define what kind of value you want to read (see MACROBUTTON_MODE below) + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + -5: structure mismatch + */ + +long __stdcall VBVMR_MacroButton_GetStatus(long nuLogicalButton, float * pValue, long bitmode); + + /** + @brief set current button value. + @param nuLogicalButton : button index: 0 to 79) + @param fValue : float 32 bit value giving the status (0.0 = OFF / 1.0 = ON). + @param bitmode: define what kind of value you want to write/modify (see MACROBUTTON_MODE below) + @return : 0: OK (no error). + -1: error + -2: no server. + -3: unknown parameter + -5: structure mismatch + */ + +long __stdcall VBVMR_MacroButton_SetStatus(long nuLogicalButton, float fValue, long bitmode); + +#define VBVMR_MACROBUTTON_MODE_DEFAULT 0x00000000 //PUSH or RELEASE button +#define VBVMR_MACROBUTTON_MODE_STATEONLY 0x00000002 //change Displayed State only +#define VBVMR_MACROBUTTON_MODE_TRIGGER 0x00000003 //change Trigger State +#define VBVMR_MACROBUTTON_MODE_COLOR 0x00000004 //change color + + + +/** @} */ + + + + + + + + + +/******************************************************************************/ +/* 'C' STRUCTURED INTERFACE */ +/******************************************************************************/ + +typedef long (__stdcall *T_VBVMR_Login)(void); +typedef long (__stdcall *T_VBVMR_Logout)(void); +typedef long (__stdcall *T_VBVMR_RunVoicemeeter)(long vType); + +typedef long (__stdcall *T_VBVMR_GetVoicemeeterType)(long * pType); +typedef long (__stdcall *T_VBVMR_GetVoicemeeterVersion)(long * pVersion); + +typedef long (__stdcall *T_VBVMR_IsParametersDirty)(void); +typedef long (__stdcall *T_VBVMR_GetParameterFloat)(char * szParamName, float * pValue); +typedef long (__stdcall *T_VBVMR_GetParameterStringA)(char * szParamName, char * szString); +typedef long (__stdcall *T_VBVMR_GetParameterStringW)(char * szParamName, unsigned short * wszString); + + +typedef long (__stdcall *T_VBVMR_GetLevel)(long nType, long nuChannel, float * pValue); +typedef long (__stdcall *T_VBVMR_GetMidiMessage)(unsigned char *pMIDIBuffer, long nbByteMax); +typedef long (__stdcall *T_VBVMR_SendMidiMessage)(unsigned char *pMIDIBuffer, long nbByteMax); + +typedef long (__stdcall *T_VBVMR_SetParameterFloat)(char * szParamName, float Value); +typedef long (__stdcall *T_VBVMR_SetParameters)(char * szParamScript); +typedef long (__stdcall *T_VBVMR_SetParametersW)(unsigned short * szParamScript); +typedef long (__stdcall *T_VBVMR_SetParameterStringA)(char * szParamName, char * szString); +typedef long (__stdcall *T_VBVMR_SetParameterStringW)(char * szParamName, unsigned short * wszString); + +typedef long (__stdcall *T_VBVMR_Output_GetDeviceNumber)(void); +typedef long (__stdcall *T_VBVMR_Output_GetDeviceDescA)(long zindex, long * nType, char * szDeviceName, char * szHardwareId); +typedef long (__stdcall *T_VBVMR_Output_GetDeviceDescW)(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId); +typedef long (__stdcall *T_VBVMR_Input_GetDeviceNumber)(void); +typedef long (__stdcall *T_VBVMR_Input_GetDeviceDescA)(long zindex, long * nType, char * szDeviceName, char * szHardwareId); +typedef long (__stdcall *T_VBVMR_Input_GetDeviceDescW)(long zindex, long * nType, unsigned short * wszDeviceName, unsigned short * wszHardwareId); + +typedef long (__stdcall *T_VBVMR_AudioCallbackRegister)(long mode, T_VBVMR_VBAUDIOCALLBACK pCallback, void * lpUser, char szClientName[64]); +typedef long (__stdcall *T_VBVMR_AudioCallbackStart)(void); +typedef long (__stdcall *T_VBVMR_AudioCallbackStop)(void); +typedef long (__stdcall *T_VBVMR_AudioCallbackUnregister)(void); + +typedef long (__stdcall *T_VBVMR_MacroButton_IsDirty)(void); +typedef long (__stdcall *T_VBVMR_MacroButton_GetStatus)(long nuLogicalButton, float * pValue, long bitmode); +typedef long (__stdcall *T_VBVMR_MacroButton_SetStatus)(long nuLogicalButton, float fValue, long bitmode); + + + +typedef struct tagVBVMR_INTERFACE +{ + T_VBVMR_Login VBVMR_Login; + T_VBVMR_Logout VBVMR_Logout; + T_VBVMR_RunVoicemeeter VBVMR_RunVoicemeeter; + T_VBVMR_GetVoicemeeterType VBVMR_GetVoicemeeterType; + T_VBVMR_GetVoicemeeterVersion VBVMR_GetVoicemeeterVersion; + T_VBVMR_IsParametersDirty VBVMR_IsParametersDirty; + T_VBVMR_GetParameterFloat VBVMR_GetParameterFloat; + T_VBVMR_GetParameterStringA VBVMR_GetParameterStringA; + T_VBVMR_GetParameterStringW VBVMR_GetParameterStringW; + + T_VBVMR_GetLevel VBVMR_GetLevel; + T_VBVMR_GetMidiMessage VBVMR_GetMidiMessage; + T_VBVMR_SendMidiMessage VBVMR_SendMidiMessage; + + T_VBVMR_SetParameterFloat VBVMR_SetParameterFloat; + T_VBVMR_SetParameters VBVMR_SetParameters; + T_VBVMR_SetParametersW VBVMR_SetParametersW; + T_VBVMR_SetParameterStringA VBVMR_SetParameterStringA; + T_VBVMR_SetParameterStringW VBVMR_SetParameterStringW; + + T_VBVMR_Output_GetDeviceNumber VBVMR_Output_GetDeviceNumber; + T_VBVMR_Output_GetDeviceDescA VBVMR_Output_GetDeviceDescA; + T_VBVMR_Output_GetDeviceDescW VBVMR_Output_GetDeviceDescW; + T_VBVMR_Input_GetDeviceNumber VBVMR_Input_GetDeviceNumber; + T_VBVMR_Input_GetDeviceDescA VBVMR_Input_GetDeviceDescA; + T_VBVMR_Input_GetDeviceDescW VBVMR_Input_GetDeviceDescW; + + T_VBVMR_AudioCallbackRegister VBVMR_AudioCallbackRegister; + T_VBVMR_AudioCallbackStart VBVMR_AudioCallbackStart; + T_VBVMR_AudioCallbackStop VBVMR_AudioCallbackStop; + T_VBVMR_AudioCallbackUnregister VBVMR_AudioCallbackUnregister; + + T_VBVMR_MacroButton_IsDirty VBVMR_MacroButton_IsDirty; + T_VBVMR_MacroButton_GetStatus VBVMR_MacroButton_GetStatus; + T_VBVMR_MacroButton_SetStatus VBVMR_MacroButton_SetStatus; + + +} T_VBVMR_INTERFACE, *PT_VBVMR_INTERFACE, *LPT_VBVMR_INTERFACE; + +#ifdef VBUSE_LOCALLIB + // internal used (not public) + void __stdcall VBVMR_SetHinstance(HINSTANCE hinst); +#endif + + + + + + + +/******************************************************************************/ +/* VBAN RT PACKET */ +/******************************************************************************/ + +#pragma pack(1) + +// short = 2 bytes +// char = 1 byte + +// COMPATIBILITY: defined structure cannot be changed. +// some field could be added at the end of the structure to keep the compatibility in the time. + +typedef struct tagVBAN_VMRT_PACKET //packedt ident: 0 +{ + unsigned char voicemeeterType; // 1 = Voicemeeter, 2= Voicemeeter Banana, 3 Potato + unsigned char reserved; // unused + unsigned short buffersize; // main stream buffer size + unsigned long voicemeeterVersion; // version like for VBVMR_GetVoicemeeterVersion() functino + unsigned long optionBits; // unused + unsigned long samplerate; // main stream samplerate + short inputLeveldB100[34]; // pre fader input peak level in dB * 100 + short outputLeveldB100[64]; // bus output peak level in dB * 100 + unsigned long TransportBit; // Transport Status + unsigned long stripState[8]; // Strip Buttons Status (see MODE bits below) + unsigned long busState[8]; // Bus Buttons Status (see MODE bits below) + short stripGaindB100Layer1[8]; // Strip Gain in dB * 100 + short stripGaindB100Layer2[8]; + short stripGaindB100Layer3[8]; + short stripGaindB100Layer4[8]; + short stripGaindB100Layer5[8]; + short stripGaindB100Layer6[8]; + short stripGaindB100Layer7[8]; + short stripGaindB100Layer8[8]; + short busGaindB100[8]; // Bus Gain in dB * 100 + char stripLabelUTF8c60[8][60]; // Strip Label + char busLabelUTF8c60[8][60]; // Bus Label +} T_VBAN_VMRT_PACKET, *PT_VBAN_VMRT_PACKET, *LPT_VBAN_VMRT_PACKET; + +#define expected_size_T_VBAN_VMRT_PACKET 1384 //1436 max + +#pragma pack() + +#define VMRTSTATE_MODE_MUTE 0x00000001 +#define VMRTSTATE_MODE_SOLO 0x00000002 +#define VMRTSTATE_MODE_MONO 0x00000004 +#define VMRTSTATE_MODE_MUTEC 0x00000008 + +#define VMRTSTATE_MODE_MIXDOWN 0x00000010 +#define VMRTSTATE_MODE_REPEAT 0x00000020 +#define VMRTSTATE_MODE_MIXDOWNB 0x00000030 +#define VMRTSTATE_MODE_COMPOSITE 0x00000040 +#define VMRTSTATE_MODE_UPMIXTV 0x00000050 +#define VMRTSTATE_MODE_UPMIX2 0x00000060 +#define VMRTSTATE_MODE_UPMIX4 0x00000070 +#define VMRTSTATE_MODE_UPMIX6 0x00000080 +#define VMRTSTATE_MODE_CENTER 0x00000090 +#define VMRTSTATE_MODE_LFE 0x000000A0 +#define VMRTSTATE_MODE_REAR 0x000000B0 + +#define VMRTSTATE_MODE_MASK 0x000000F0 + +#define VMRTSTATE_MODE_EQ 0x00000100 +#define VMRTSTATE_MODE_CROSS 0x00000200 +#define VMRTSTATE_MODE_EQB 0x00000800 + +#define VMRTSTATE_MODE_BUSA 0x00001000 +#define VMRTSTATE_MODE_BUSA1 0x00001000 +#define VMRTSTATE_MODE_BUSA2 0x00002000 +#define VMRTSTATE_MODE_BUSA3 0x00004000 +#define VMRTSTATE_MODE_BUSA4 0x00008000 +#define VMRTSTATE_MODE_BUSA5 0x00080000 + +#define VMRTSTATE_MODE_BUSB 0x00010000 +#define VMRTSTATE_MODE_BUSB1 0x00010000 +#define VMRTSTATE_MODE_BUSB2 0x00020000 +#define VMRTSTATE_MODE_BUSB3 0x00040000 + +#define VMRTSTATE_MODE_PAN0 0x00000000 +#define VMRTSTATE_MODE_PANCOLOR 0x00100000 +#define VMRTSTATE_MODE_PANMOD 0x00200000 +#define VMRTSTATE_MODE_PANMASK 0x00F00000 + +#define VMRTSTATE_MODE_POSTFX_R 0x01000000 +#define VMRTSTATE_MODE_POSTFX_D 0x02000000 +#define VMRTSTATE_MODE_POSTFX1 0x04000000 +#define VMRTSTATE_MODE_POSTFX2 0x08000000 + +#define VMRTSTATE_MODE_SEL 0x10000000 +#define VMRTSTATE_MODE_MONITOR 0x20000000 + + +#pragma pack(1) + +// long = 4 bytes +// short = 2 bytes +// char = 1 byte +// float = 4 bytes + +typedef struct tagVBAN_VMPARAM_STRIP +{ + long mode; + float dblevel; // x 100 + short Audibility; // x 100 + short pos3D_x; // x 100 + short pos3D_y; // x 100 + short posColor_x; // x 100 + short posColor_y; // x 100 + short EQgain1; // x 100 + short EQgain2; // x 100 + short EQgain3; // x 100 + + //first channel parametric EQ + char PEQ_eqOn[6]; // 0 or 1 + char PEQ_eqtype[6]; // see define below + float PEQ_eqgain[6]; + float PEQ_eqfreq[6]; + float PEQ_eqq[6]; + + short Audibility_c; // x 100 + short Audibility_g; // x 100 + short Audibility_d; // x 100 + short posMod_x; // x 100 + short posMod_y; // x 100 + short send_reverb; // x 100 + short send_delay; // x 100 + short send_fx1; // x 100 + short send_fx2; // x 100 + short dblimit; // x 100 + short nKaraoke; // x 100 + + short COMP_gain_in; // x 100 + short COMP_attack_ms; // x 10 + short COMP_release_ms; // x 10 + short COMP_n_knee; // x 100 + short COMP_comprate; // x 100 + short COMP_threshold; // x 100 + short COMP_c_enabled; + short COMP_c_auto; + short COMP_gain_out; // x 100 + + short GATE_dBThreshold_in; // x 100 + short GATE_dBDamping_max; // x 100 + short GATE_BP_Sidechain; // x 10 + short GATE_attack_ms; // x 10 + short GATE_hold_ms; // x 10 + short GATE_release_ms; // x 10 + + short DenoiserThreshold; // x 100 + short PitchEnabled; + short Pitch_DryWet; // x 100 + short Pitch_Value; // x 100 + short Pitch_formant_lo; // x 100 + short Pitch_formant_med; // x 100 + short Pitch_formant_high; // x 100 + +} T_VBAN_VMPARAM_STRIP, *PT_VBAN_VMPARAM_STRIP, *LPT_VBAN_VMPARAM_STRIP; + +#define VMRT_EQTYPE_PEQ 0 +#define VMRT_EQTYPE_NOTCH 1 +#define VMRT_EQTYPE_BPF 2 +#define VMRT_EQTYPE_LPF 3 +#define VMRT_EQTYPE_HPF 4 +#define VMRT_EQTYPE_LOSHELF 5 +#define VMRT_EQTYPE_HISHELF 6 + + +#define expected_size_T_VBAN_VMPARAM_STRIP (8+ (8 * sizeof(short)) + (2*6) + (3 * 6 * sizeof(float)) + ((11 + 9 + 6 + 7) * sizeof(short))) +//170 + +typedef struct tagVBAN_VMPARAMSTRIP_PACKET //packedt ident: 1 +{ + unsigned char voicemeeterType; // 1 = Voicemeeter, 2= Voicemeeter Banana, 3 Potato + unsigned char reserved; // unused + unsigned short buffersize; // main stream buffer size + unsigned long voicemeeterVersion; // version like for VBVMR_GetVoicemeeterVersion() functino + unsigned long optionBits; // unused + unsigned long samplerate; // main stream samplerate + T_VBAN_VMPARAM_STRIP Strips[8]; // all input strips +} T_VBAN_VMPARAMSTRIP_PACKET, *PT_VBAN_VMPARAMSTRIP_PACKET, *LPT_VBAN_VMPARAMSTRIP_PACKET; + +#pragma pack() + +#define expected_size_T_VBAN_VMPARAMSTRIP_PACKET ((4 * 4) + (expected_size_T_VBAN_VMPARAM_STRIP * 8)) //1436 max +//1376 + +/******************************************************************************/ +/* LOCAL FUNCTIONS */ +/******************************************************************************/ + +long VBVMR_LocalInit(void); +long VBVMR_LocalEnd(void); +void * VBVMR_GetRequestVB0STREAMPTR(void); + +long VBVMR_SetParametersWEx(unsigned short * szParamScript, long fCopyToClient); + +long VBVMR_LoginEx(long properties); + +long VBVMR_MB_PushSettings(void * lpParam); + + + + + +#ifdef __cplusplus +} +#endif + +#endif /*__VOICEMEETER_REMOTE_H__*/ + + diff --git a/include/cdll.h b/include/cdll.h new file mode 100644 index 0000000..19a59fb --- /dev/null +++ b/include/cdll.h @@ -0,0 +1,9 @@ +#include +#include "VoicemeeterRemote.h" + +#ifndef __CDLL_H__ +#define __CDLL_H__ + +long initialize_dll_interfaces(T_VBVMR_INTERFACE *iVMR); + +#endif /*__CDLL_H__*/ \ No newline at end of file diff --git a/include/vmr.h b/include/vmr.h new file mode 100644 index 0000000..65cc953 --- /dev/null +++ b/include/vmr.h @@ -0,0 +1,22 @@ +#include +#include "voicemeeterRemote.h" + +#ifndef __VMR_H__ +#define __VMR_H__ + +long login(T_VBVMR_INTERFACE *iVMR); +long logout(T_VBVMR_INTERFACE *iVMR); +long run_voicemeeter(T_VBVMR_INTERFACE *iVMR); +long type(T_VBVMR_INTERFACE *iVMR, long *type); +long version(T_VBVMR_INTERFACE *iVMR, long *version); + +bool pdirty(T_VBVMR_INTERFACE *iVMR); +long set_parameters(T_VBVMR_INTERFACE *iVMR, char *command); + +bool mdirty(T_VBVMR_INTERFACE *iVMR); +long macrobutton_getstatus(T_VBVMR_INTERFACE *iVMR, long n, float *val, long mode); +long macrobutton_setstatus(T_VBVMR_INTERFACE *iVMR, long n, float val, long mode); + +void clear_dirty(T_VBVMR_INTERFACE *iVMR); + +#endif \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..59bd2ab --- /dev/null +++ b/makefile @@ -0,0 +1,33 @@ +program = vmrcli + +CC = gcc +SRC_DIR := src +OBJ_DIR := obj +BIN_DIR := bin + +EXE := $(BIN_DIR)/$(program).exe +SRC := $(wildcard $(SRC_DIR)/*.c) +OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) + +CPPFLAGS := -Iinclude -MMD -MP +CFLAGS = -O -Wall -W -pedantic -ansi -std=c99 +LDFLAGS := -Llib +LDLIBS := -lm + +.PHONY: all clean + +all: $(EXE) + +$(EXE): $(OBJ) | $(BIN_DIR) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +$(BIN_DIR) $(OBJ_DIR): + mkdir -p $@ + +clean: + @$(RM) -rv $(EXE) $(OBJ_DIR) + +-include $(OBJ:.o=.d) diff --git a/src/cdll.c b/src/cdll.c new file mode 100644 index 0000000..14e550e --- /dev/null +++ b/src/cdll.c @@ -0,0 +1,172 @@ +#include +#include +#include "cdll.h" + +/*******************************************************************************/ +/** GET VOICEMEETER DIRECTORY **/ +/*******************************************************************************/ + +static char uninstDirKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + +#define INSTALLER_UNINST_KEY "VB:Voicemeeter {17359A74-1236-5467}" + +void remove_name_in_path(char *szPath) +{ + char *p = szPath; + + while (*p++) + ; + while (p > szPath && *p != '\\') + p--; + if (*p == '\\') + *p = '\0'; +} + +#ifndef KEY_WOW64_32KEY +#define KEY_WOW64_32KEY 0x0200 +#endif + +bool __cdecl registry_get_voicemeeter_folder(char *szDir) +{ + char szKey[256]; + char sss[1024]; + DWORD nnsize = 1024; + HKEY hkResult; + LONG rep; + DWORD pptype = REG_SZ; + sss[0] = 0; + + // build Voicemeeter uninstallation key + strcpy(szKey, uninstDirKey); + strcat(szKey, "\\"); + strcat(szKey, INSTALLER_UNINST_KEY); + + // open key + rep = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkResult); + if (rep != ERROR_SUCCESS) + { + // if not present we consider running in 64bit mode and force to read 32bit registry + rep = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ | KEY_WOW64_32KEY, &hkResult); + } + if (rep != ERROR_SUCCESS) + return false; + // read uninstall path from registry + rep = RegQueryValueEx(hkResult, "UninstallString", 0, &pptype, (unsigned char *)sss, &nnsize); + RegCloseKey(hkResult); + + if (pptype != REG_SZ) + return false; + if (rep != ERROR_SUCCESS) + return false; + // remove name to get the path only + remove_name_in_path(sss); + if (nnsize > 512) + nnsize = 512; + strncpy(szDir, sss, nnsize); + + return true; +} + +/*******************************************************************************/ +/** GET DLL INTERFACE **/ +/*******************************************************************************/ +static HMODULE G_H_Module = NULL; + +long initialize_dll_interfaces(T_VBVMR_INTERFACE *iVMR) +{ + char szDllName[1024]; + memset(iVMR, 0, sizeof(T_VBVMR_INTERFACE)); + + // get folder where is installed Voicemeeter + if (!registry_get_voicemeeter_folder(szDllName)) + { + // voicemeeter not installed + return -100; + } + // use right dll according O/S type + if (sizeof(void *) == 8) + strcat(szDllName, "\\VoicemeeterRemote64.dll"); + else + strcat(szDllName, "\\VoicemeeterRemote.dll"); + + // Load Dll + G_H_Module = LoadLibrary(szDllName); + if (G_H_Module == NULL) + return -101; + + // Get function pointers + iVMR->VBVMR_Login = (T_VBVMR_Login)GetProcAddress(G_H_Module, "VBVMR_Login"); + iVMR->VBVMR_Logout = (T_VBVMR_Logout)GetProcAddress(G_H_Module, "VBVMR_Logout"); + iVMR->VBVMR_RunVoicemeeter = (T_VBVMR_RunVoicemeeter)GetProcAddress(G_H_Module, "VBVMR_RunVoicemeeter"); + iVMR->VBVMR_GetVoicemeeterType = (T_VBVMR_GetVoicemeeterType)GetProcAddress(G_H_Module, "VBVMR_GetVoicemeeterType"); + iVMR->VBVMR_GetVoicemeeterVersion = (T_VBVMR_GetVoicemeeterVersion)GetProcAddress(G_H_Module, "VBVMR_GetVoicemeeterVersion"); + + iVMR->VBVMR_IsParametersDirty = (T_VBVMR_IsParametersDirty)GetProcAddress(G_H_Module, "VBVMR_IsParametersDirty"); + iVMR->VBVMR_GetParameterFloat = (T_VBVMR_GetParameterFloat)GetProcAddress(G_H_Module, "VBVMR_GetParameterFloat"); + iVMR->VBVMR_GetParameterStringA = (T_VBVMR_GetParameterStringA)GetProcAddress(G_H_Module, "VBVMR_GetParameterStringA"); + iVMR->VBVMR_GetParameterStringW = (T_VBVMR_GetParameterStringW)GetProcAddress(G_H_Module, "VBVMR_GetParameterStringW"); + iVMR->VBVMR_GetLevel = (T_VBVMR_GetLevel)GetProcAddress(G_H_Module, "VBVMR_GetLevel"); + iVMR->VBVMR_GetMidiMessage = (T_VBVMR_GetMidiMessage)GetProcAddress(G_H_Module, "VBVMR_GetMidiMessage"); + + iVMR->VBVMR_SetParameterFloat = (T_VBVMR_SetParameterFloat)GetProcAddress(G_H_Module, "VBVMR_SetParameterFloat"); + iVMR->VBVMR_SetParameters = (T_VBVMR_SetParameters)GetProcAddress(G_H_Module, "VBVMR_SetParameters"); + iVMR->VBVMR_SetParametersW = (T_VBVMR_SetParametersW)GetProcAddress(G_H_Module, "VBVMR_SetParametersW"); + iVMR->VBVMR_SetParameterStringA = (T_VBVMR_SetParameterStringA)GetProcAddress(G_H_Module, "VBVMR_SetParameterStringA"); + iVMR->VBVMR_SetParameterStringW = (T_VBVMR_SetParameterStringW)GetProcAddress(G_H_Module, "VBVMR_SetParameterStringW"); + + iVMR->VBVMR_Output_GetDeviceNumber = (T_VBVMR_Output_GetDeviceNumber)GetProcAddress(G_H_Module, "VBVMR_Output_GetDeviceNumber"); + iVMR->VBVMR_Output_GetDeviceDescA = (T_VBVMR_Output_GetDeviceDescA)GetProcAddress(G_H_Module, "VBVMR_Output_GetDeviceDescA"); + iVMR->VBVMR_Output_GetDeviceDescW = (T_VBVMR_Output_GetDeviceDescW)GetProcAddress(G_H_Module, "VBVMR_Output_GetDeviceDescW"); + iVMR->VBVMR_Input_GetDeviceNumber = (T_VBVMR_Input_GetDeviceNumber)GetProcAddress(G_H_Module, "VBVMR_Input_GetDeviceNumber"); + iVMR->VBVMR_Input_GetDeviceDescA = (T_VBVMR_Input_GetDeviceDescA)GetProcAddress(G_H_Module, "VBVMR_Input_GetDeviceDescA"); + iVMR->VBVMR_Input_GetDeviceDescW = (T_VBVMR_Input_GetDeviceDescW)GetProcAddress(G_H_Module, "VBVMR_Input_GetDeviceDescW"); + + // check pointers are valid + if (iVMR->VBVMR_Login == NULL) + return -1; + if (iVMR->VBVMR_Logout == NULL) + return -2; + if (iVMR->VBVMR_RunVoicemeeter == NULL) + return -2; + if (iVMR->VBVMR_GetVoicemeeterType == NULL) + return -3; + if (iVMR->VBVMR_GetVoicemeeterVersion == NULL) + return -4; + if (iVMR->VBVMR_IsParametersDirty == NULL) + return -5; + if (iVMR->VBVMR_GetParameterFloat == NULL) + return -6; + if (iVMR->VBVMR_GetParameterStringA == NULL) + return -7; + if (iVMR->VBVMR_GetParameterStringW == NULL) + return -8; + if (iVMR->VBVMR_GetLevel == NULL) + return -9; + if (iVMR->VBVMR_SetParameterFloat == NULL) + return -10; + if (iVMR->VBVMR_SetParameters == NULL) + return -11; + if (iVMR->VBVMR_SetParametersW == NULL) + return -12; + if (iVMR->VBVMR_SetParameterStringA == NULL) + return -13; + if (iVMR->VBVMR_SetParameterStringW == NULL) + return -14; + if (iVMR->VBVMR_GetMidiMessage == NULL) + return -15; + + if (iVMR->VBVMR_Output_GetDeviceNumber == NULL) + return -30; + if (iVMR->VBVMR_Output_GetDeviceDescA == NULL) + return -31; + if (iVMR->VBVMR_Output_GetDeviceDescW == NULL) + return -32; + if (iVMR->VBVMR_Input_GetDeviceNumber == NULL) + return -33; + if (iVMR->VBVMR_Input_GetDeviceDescA == NULL) + return -34; + if (iVMR->VBVMR_Input_GetDeviceDescW == NULL) + return -35; + + return 0; +} \ No newline at end of file diff --git a/src/vmr.c b/src/vmr.c new file mode 100644 index 0000000..ff9aac6 --- /dev/null +++ b/src/vmr.c @@ -0,0 +1,81 @@ +#include +#include +#include "vmr.h" + +enum kind +{ + BASIC = 1, + BANANA, + POTATO, + POTATOX64 = 6 +} kind; + +long login(T_VBVMR_INTERFACE *iVMR) +{ + int rep; + + rep = iVMR->VBVMR_Login(); + if (rep == 1) + { + rep = run_voicemeeter(iVMR); + puts("Launching Voicemeeter GUI"); + Sleep(1200); + } + return rep; +} + +long logout(T_VBVMR_INTERFACE *iVMR) +{ + Sleep(20); /* give time for last command */ + return iVMR->VBVMR_Logout(); +} + +long run_voicemeeter(T_VBVMR_INTERFACE *iVMR) +{ + int kind = POTATO; + if (sizeof(void *) == 8) + kind = POTATOX64; + return iVMR->VBVMR_RunVoicemeeter((long)kind); +} + +long type(T_VBVMR_INTERFACE *iVMR, long *type) +{ + return iVMR->VBVMR_GetVoicemeeterType(type); +} + +long version(T_VBVMR_INTERFACE *iVMR, long *version) +{ + return iVMR->VBVMR_GetVoicemeeterType(version); +} + +bool pdirty(T_VBVMR_INTERFACE *iVMR) +{ + return iVMR->VBVMR_IsParametersDirty() == 1; +} + +long set_parameters(T_VBVMR_INTERFACE *iVMR, char *command) +{ + return iVMR->VBVMR_SetParameters(command); +} + +bool mdirty(T_VBVMR_INTERFACE *iVMR) +{ + return iVMR->VBVMR_MacroButton_IsDirty() == 1; +} + +long macrobutton_getstatus(T_VBVMR_INTERFACE *iVMR, long n, float *val, long mode) +{ + return iVMR->VBVMR_MacroButton_GetStatus(n, val, mode); +} + +long macrobutton_setstatus(T_VBVMR_INTERFACE *iVMR, long n, float val, long mode) +{ + return iVMR->VBVMR_MacroButton_SetStatus(n, val, mode); +} + +void clear_dirty(T_VBVMR_INTERFACE *iVMR) +{ + Sleep(30); + while (pdirty(iVMR)) + Sleep(1); +} \ No newline at end of file diff --git a/src/vmrcli.c b/src/vmrcli.c new file mode 100644 index 0000000..dece72a --- /dev/null +++ b/src/vmrcli.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include "cdll.h" +#include "vmr.h" + +#define MAX_LINE 1024 + +int init_voicemeeter(T_VBVMR_INTERFACE *vmr); +void interactive(T_VBVMR_INTERFACE *vmr); + +int main(int argc, char *argv[]) +{ + bool iflag = false; + int c; + + while ((c = getopt(argc, argv, "i")) != -1) + { + switch (c) + { + case 'i': + iflag = true; + break; + default: + abort(); + } + } + + static T_VBVMR_INTERFACE iVMR; + T_VBVMR_INTERFACE *vmr = &iVMR; + + int rep = init_voicemeeter(vmr); + if (rep) + { + exit(EXIT_FAILURE); + } + + if (iflag) + { + puts("Interactive mode enabled. Enter 'Q' to exit."); + interactive(vmr); + } + else + { + for (int i = optind; i < argc; i++) + { + set_parameters(vmr, argv[i]); + } + } + + rep = logout(vmr); + if (!rep) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +int init_voicemeeter(T_VBVMR_INTERFACE *vmr) +{ + int rep = initialize_dll_interfaces(vmr); + if (rep < 0) + { + if (rep == -100) + { + fputs("Voicemeeter is not installed", stderr); + } + else + { + fprintf(stderr, "Error loading Voicemeeter dll with code %d\n", rep); + } + return rep; + } + + rep = login(vmr); + if (rep != 0) + { + fputs("Error logging into Voicemeeter", stderr); + return rep; + } + clear_dirty(vmr); + + return 0; +} + +void interactive(T_VBVMR_INTERFACE *vmr) +{ + char input[MAX_LINE]; + + while (fgets(input, MAX_LINE, stdin) != NULL) + { + if (strncmp(input, "Q", 1) == 0 || strncmp(input, "q", 1) == 0) + break; + + set_parameters(vmr, input); + } +} \ No newline at end of file