mirror of
				https://github.com/onyx-and-iris/vmrcli.git
				synced 2025-10-31 05:01:48 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "8bdbfe9b0419812402b7feff78b877cad75c1834" and "a28db25bcca7265b24cc1917feba0662fb8cbc50" have entirely different histories.
		
	
	
		
			8bdbfe9b04
			...
			a28db25bcc
		
	
		
| @ -13,7 +13,7 @@ | |||||||
| ## `Use` | ## `Use` | ||||||
| 
 | 
 | ||||||
| ```powershell | ```powershell | ||||||
| ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-m] [-s] <api commands> | ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-m] [-s] <api commands> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Where: | Where: | ||||||
| @ -23,7 +23,6 @@ Where: | |||||||
| - `k`: The kind of Voicemeeter (basic, banana or potato). Use this to launch the GUI. | - `k`: The kind of Voicemeeter (basic, banana or potato). Use this to launch the GUI. | ||||||
| - `D`: Set log level 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL | - `D`: Set log level 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL | ||||||
| - `v`: Enable extra console output (toggle, set messages) | - `v`: Enable extra console output (toggle, set messages) | ||||||
| - `c`: Load a user configuration (given the file name or a full path) |  | ||||||
| - `m`: Launch the MacroButtons application | - `m`: Launch the MacroButtons application | ||||||
| - `s`: Launch the StreamerView application | - `s`: Launch the StreamerView application | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,6 @@ | |||||||
| 
 | 
 | ||||||
| #include "VoicemeeterRemote.h" | #include "VoicemeeterRemote.h" | ||||||
| 
 | 
 | ||||||
| PT_VMR create_interface(); | long initialize_dll_interfaces(PT_VMR vmr); | ||||||
| 
 | 
 | ||||||
| #endif /*__CDLL_H__*/ | #endif /*__CDLL_H__*/ | ||||||
							
								
								
									
										117
									
								
								src/cdll.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/cdll.c
									
									
									
									
									
								
							| @ -3,40 +3,63 @@ | |||||||
| #include <windows.h> | #include <windows.h> | ||||||
| #include "cdll.h" | #include "cdll.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
| #include "log.h" |  | ||||||
| 
 | 
 | ||||||
| static T_VBVMR_INTERFACE iVMR; | /*******************************************************************************/ | ||||||
|  | /**                           GET VOICEMEETER DIRECTORY                       **/ | ||||||
|  | /*******************************************************************************/ | ||||||
| 
 | 
 | ||||||
| static long initialize_dll_interfaces(PT_VMR vmr); | #define INSTALLER_UNINST_KEY "VB:Voicemeeter {17359A74-1236-5467}" | ||||||
| static bool registry_get_voicemeeter_folder(char *szDir); |  | ||||||
| 
 | 
 | ||||||
| PT_VMR create_interface() | #ifndef KEY_WOW64_32KEY | ||||||
|  | #define KEY_WOW64_32KEY 0x0200 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | bool __cdecl registry_get_voicemeeter_folder(char *szDir) | ||||||
| { | { | ||||||
|     PT_VMR vmr = &iVMR; |     char szKey[256]; | ||||||
|     int rep; |     char sss[1024]; | ||||||
|  |     DWORD nnsize = 1024; | ||||||
|  |     HKEY hkResult; | ||||||
|  |     LONG rep; | ||||||
|  |     DWORD pptype = REG_SZ; | ||||||
|  |     sss[0] = 0; | ||||||
|  |     const char uninstDirKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; | ||||||
| 
 | 
 | ||||||
|     rep = initialize_dll_interfaces(vmr); |     // build Voicemeeter uninstallation key
 | ||||||
|     if (rep < 0) |     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 (rep == -100) |         // 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); | ||||||
|             log_fatal("Voicemeeter is not installed"); |  | ||||||
|             exit(EXIT_FAILURE); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             log_fatal("Error loading Voicemeeter dll with code %d\n", rep); |  | ||||||
|             exit(EXIT_FAILURE); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |     if (rep != ERROR_SUCCESS) | ||||||
|  |         return false; | ||||||
|  |     // read uninstall path from registry
 | ||||||
|  |     rep = RegQueryValueEx(hkResult, "UninstallString", 0, &pptype, (unsigned char *)sss, &nnsize); | ||||||
|  |     RegCloseKey(hkResult); | ||||||
| 
 | 
 | ||||||
|     return vmr; |     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                          **/ | /**                                GET DLL INTERFACE                          **/ | ||||||
| /*******************************************************************************/ | /*******************************************************************************/ | ||||||
| static long initialize_dll_interfaces(PT_VMR vmr) | long initialize_dll_interfaces(PT_VMR vmr) | ||||||
| { | { | ||||||
|     HMODULE G_H_Module = NULL; |     HMODULE G_H_Module = NULL; | ||||||
|     char szDllName[1024]; |     char szDllName[1024]; | ||||||
| @ -145,56 +168,4 @@ static long initialize_dll_interfaces(PT_VMR vmr) | |||||||
|         return -38; |         return -38; | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*******************************************************************************/ |  | ||||||
| /**                           GET VOICEMEETER DIRECTORY                       **/ |  | ||||||
| /*******************************************************************************/ |  | ||||||
| 
 |  | ||||||
| #define INSTALLER_UNINST_KEY "VB:Voicemeeter {17359A74-1236-5467}" |  | ||||||
| 
 |  | ||||||
| #ifndef KEY_WOW64_32KEY |  | ||||||
| #define KEY_WOW64_32KEY 0x0200 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| static bool 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; |  | ||||||
|     const char uninstDirKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; |  | ||||||
| 
 |  | ||||||
|     // 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; |  | ||||||
| } | } | ||||||
							
								
								
									
										67
									
								
								src/vmrcli.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								src/vmrcli.c
									
									
									
									
									
								
							| @ -36,10 +36,12 @@ struct result | |||||||
|     } val; |     } val; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static bool vflag = false; | static T_VBVMR_INTERFACE iVMR; | ||||||
|  | bool vflag = false; | ||||||
| 
 | 
 | ||||||
| void help(void); | void help(void); | ||||||
| enum kind set_kind(char *kval); | enum kind set_kind(char *kval); | ||||||
|  | int init_voicemeeter(PT_VMR vmr, enum kind kind); | ||||||
| void interactive(PT_VMR vmr); | void interactive(PT_VMR vmr); | ||||||
| void parse_input(PT_VMR vmr, char *input, int len); | void parse_input(PT_VMR vmr, char *input, int len); | ||||||
| void parse_command(PT_VMR vmr, char *command); | void parse_command(PT_VMR vmr, char *command); | ||||||
| @ -49,11 +51,9 @@ int main(int argc, char *argv[]) | |||||||
| { | { | ||||||
|     bool iflag = false, |     bool iflag = false, | ||||||
|          mflag = false, |          mflag = false, | ||||||
|          sflag = false, |          sflag = false; | ||||||
|          cflag = false; |  | ||||||
|     int opt; |     int opt; | ||||||
|     int dvalue; |     int dvalue; | ||||||
|     char *cvalue; |  | ||||||
|     enum kind kind = BANANAX64; |     enum kind kind = BANANAX64; | ||||||
| 
 | 
 | ||||||
|     if (argc == 1) |     if (argc == 1) | ||||||
| @ -64,7 +64,7 @@ int main(int argc, char *argv[]) | |||||||
| 
 | 
 | ||||||
|     log_set_level(LOG_WARN); |     log_set_level(LOG_WARN); | ||||||
| 
 | 
 | ||||||
|     while ((opt = getopt(argc, argv, "hk:msc:iD:v")) != -1) |     while ((opt = getopt(argc, argv, "hk:msiD:v")) != -1) | ||||||
|     { |     { | ||||||
|         switch (opt) |         switch (opt) | ||||||
|         { |         { | ||||||
| @ -85,10 +85,6 @@ int main(int argc, char *argv[]) | |||||||
|         case 's': |         case 's': | ||||||
|             sflag = true; |             sflag = true; | ||||||
|             break; |             break; | ||||||
|         case 'c': |  | ||||||
|             cflag = true; |  | ||||||
|             cvalue = optarg; |  | ||||||
|             break; |  | ||||||
|         case 'i': |         case 'i': | ||||||
|             iflag = true; |             iflag = true; | ||||||
|             break; |             break; | ||||||
| @ -113,12 +109,11 @@ int main(int argc, char *argv[]) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PT_VMR vmr = create_interface(); |     PT_VMR vmr = &iVMR; | ||||||
| 
 | 
 | ||||||
|     int rep = login(vmr, kind); |     int rep = init_voicemeeter(vmr, kind); | ||||||
|     if (rep != 0) |     if (rep != 0) | ||||||
|     { |     { | ||||||
|         log_fatal("Error logging into the Voicemeeter API"); |  | ||||||
|         exit(EXIT_FAILURE); |         exit(EXIT_FAILURE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -134,12 +129,6 @@ int main(int argc, char *argv[]) | |||||||
|         run_voicemeeter(vmr, STREAMERVIEW); |         run_voicemeeter(vmr, STREAMERVIEW); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (cflag) |  | ||||||
|     { |  | ||||||
|         log_info("Profile %s loaded", cvalue); |  | ||||||
|         set_parameter_string(vmr, "command.load", cvalue); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (iflag) |     if (iflag) | ||||||
|     { |     { | ||||||
|         puts("Interactive mode enabled. Enter 'Q' to exit."); |         puts("Interactive mode enabled. Enter 'Q' to exit."); | ||||||
| @ -155,14 +144,9 @@ int main(int argc, char *argv[]) | |||||||
| 
 | 
 | ||||||
|     rep = logout(vmr); |     rep = logout(vmr); | ||||||
|     if (rep == 0) |     if (rep == 0) | ||||||
|     { |  | ||||||
|         return EXIT_SUCCESS; |         return EXIT_SUCCESS; | ||||||
|     } |  | ||||||
|     else |     else | ||||||
|     { |  | ||||||
|         log_fatal("Error logging out of the Voicemeeter API"); |  | ||||||
|         return EXIT_FAILURE; |         return EXIT_FAILURE; | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -172,14 +156,13 @@ int main(int argc, char *argv[]) | |||||||
| void help() | void help() | ||||||
| { | { | ||||||
|     puts( |     puts( | ||||||
|         "Usage: ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-m] [-s] <api commands>\n" |         "Usage: ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-m] [-s] <api commands>\n" | ||||||
|         "Where: \n" |         "Where: \n" | ||||||
|         "\th: Prints the help message\n" |         "\th: Prints the help message\n" | ||||||
|         "\ti: Enable interactive mode\n" |         "\ti: Enable interactive mode\n" | ||||||
|         "\tk: The kind of Voicemeeter (basic, banana, potato)\n" |         "\tk: The kind of Voicemeeter (basic, banana, potato)\n" | ||||||
|         "\tD: Set log level 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL\n" |         "\tD: Set log level 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL\n" | ||||||
|         "\tv: Enable extra console output (toggle, set messages)\n" |         "\tv: Enable extra console output (toggle, set messages)\n" | ||||||
|         "\tc: Load a user configuration (given the file name or a full path)\n" |  | ||||||
|         "\tm: Launch the MacroButtons application\n" |         "\tm: Launch the MacroButtons application\n" | ||||||
|         "\ts: Launch the StreamerView application"); |         "\ts: Launch the StreamerView application"); | ||||||
| } | } | ||||||
| @ -219,6 +202,40 @@ enum kind set_kind(char *kval) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Defines the DLL interface as a struct. | ||||||
|  |  * Logs into the API. | ||||||
|  |  * | ||||||
|  |  * @param vmr The API interface as a struct | ||||||
|  |  * @param kind | ||||||
|  |  * @return int | ||||||
|  |  */ | ||||||
|  | int init_voicemeeter(PT_VMR vmr, enum kind kind) | ||||||
|  | { | ||||||
|  |     int rep = initialize_dll_interfaces(vmr); | ||||||
|  |     if (rep < 0) | ||||||
|  |     { | ||||||
|  |         if (rep == -100) | ||||||
|  |         { | ||||||
|  |             log_fatal("Voicemeeter is not installed"); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             log_fatal("Error loading Voicemeeter dll with code %d\n", rep); | ||||||
|  |         } | ||||||
|  |         return rep; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     rep = login(vmr, kind); | ||||||
|  |     if (rep != 0) | ||||||
|  |     { | ||||||
|  |         log_fatal("Error logging into Voicemeeter"); | ||||||
|  |         return rep; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Continuously read lines from stdin. |  * @brief Continuously read lines from stdin. | ||||||
|  * Break if 'Q' is entered on the interactive prompt. |  * Break if 'Q' is entered on the interactive prompt. | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user