mirror of
				https://github.com/onyx-and-iris/vmrcli.git
				synced 2025-10-31 05:01:48 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			a28db25bcc
			...
			8bdbfe9b04
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8bdbfe9b04 | |||
| f87977165a | |||
| 36eadb4b58 | |||
| 930093da7f | 
| @ -13,7 +13,7 @@ | |||||||
| ## `Use` | ## `Use` | ||||||
| 
 | 
 | ||||||
| ```powershell | ```powershell | ||||||
| ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-m] [-s] <api commands> | ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-m] [-s] <api commands> | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Where: | Where: | ||||||
| @ -23,6 +23,7 @@ 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" | ||||||
| 
 | 
 | ||||||
| long initialize_dll_interfaces(PT_VMR vmr); | PT_VMR create_interface(); | ||||||
| 
 | 
 | ||||||
| #endif /*__CDLL_H__*/ | #endif /*__CDLL_H__*/ | ||||||
							
								
								
									
										117
									
								
								src/cdll.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/cdll.c
									
									
									
									
									
								
							| @ -3,63 +3,40 @@ | |||||||
| #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                       **/ |  | ||||||
| /*******************************************************************************/ |  | ||||||
| 
 | 
 | ||||||
| #define INSTALLER_UNINST_KEY "VB:Voicemeeter {17359A74-1236-5467}" | static long initialize_dll_interfaces(PT_VMR vmr); | ||||||
|  | static bool registry_get_voicemeeter_folder(char *szDir); | ||||||
| 
 | 
 | ||||||
| #ifndef KEY_WOW64_32KEY | PT_VMR create_interface() | ||||||
| #define KEY_WOW64_32KEY 0x0200 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| bool __cdecl registry_get_voicemeeter_folder(char *szDir) |  | ||||||
| { | { | ||||||
|     char szKey[256]; |     PT_VMR vmr = &iVMR; | ||||||
|     char sss[1024]; |     int rep; | ||||||
|     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
 |     rep = initialize_dll_interfaces(vmr); | ||||||
|     strcpy(szKey, uninstDirKey); |     if (rep < 0) | ||||||
|     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
 |         if (rep == -100) | ||||||
|         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); |  | ||||||
| 
 | 
 | ||||||
|     if (pptype != REG_SZ) |     return vmr; | ||||||
|         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                          **/ | ||||||
| /*******************************************************************************/ | /*******************************************************************************/ | ||||||
| long initialize_dll_interfaces(PT_VMR vmr) | static long initialize_dll_interfaces(PT_VMR vmr) | ||||||
| { | { | ||||||
|     HMODULE G_H_Module = NULL; |     HMODULE G_H_Module = NULL; | ||||||
|     char szDllName[1024]; |     char szDllName[1024]; | ||||||
| @ -169,3 +146,55 @@ long initialize_dll_interfaces(PT_VMR vmr) | |||||||
| 
 | 
 | ||||||
|     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,12 +36,10 @@ struct result | |||||||
|     } val; |     } val; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static T_VBVMR_INTERFACE iVMR; | static bool vflag = false; | ||||||
| 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); | ||||||
| @ -51,9 +49,11 @@ 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:msiD:v")) != -1) |     while ((opt = getopt(argc, argv, "hk:msc:iD:v")) != -1) | ||||||
|     { |     { | ||||||
|         switch (opt) |         switch (opt) | ||||||
|         { |         { | ||||||
| @ -85,6 +85,10 @@ 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; | ||||||
| @ -109,11 +113,12 @@ int main(int argc, char *argv[]) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PT_VMR vmr = &iVMR; |     PT_VMR vmr = create_interface(); | ||||||
| 
 | 
 | ||||||
|     int rep = init_voicemeeter(vmr, kind); |     int rep = login(vmr, kind); | ||||||
|     if (rep != 0) |     if (rep != 0) | ||||||
|     { |     { | ||||||
|  |         log_fatal("Error logging into the Voicemeeter API"); | ||||||
|         exit(EXIT_FAILURE); |         exit(EXIT_FAILURE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -129,6 +134,12 @@ 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."); | ||||||
| @ -144,9 +155,14 @@ 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; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -156,13 +172,14 @@ int main(int argc, char *argv[]) | |||||||
| void help() | void help() | ||||||
| { | { | ||||||
|     puts( |     puts( | ||||||
|         "Usage: ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-m] [-s] <api commands>\n" |         "Usage: ./vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-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"); | ||||||
| } | } | ||||||
| @ -202,40 +219,6 @@ 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