Compare commits

..

No commits in common. "main" and "v0.10.0" have entirely different histories.

12 changed files with 114 additions and 276 deletions

1
.env
View File

@ -1 +0,0 @@
LOG_USE_COLOR=yes

3
.gitignore vendored
View File

@ -51,9 +51,6 @@ Module.symvers
Mkfile.old
dkms.conf
# Task Runner
.task/
.vscode/
test*

View File

@ -2,9 +2,9 @@
## `Tested against`
- Basic 1.1.1.9
- Banana 2.1.1.9
- Potato 3.1.1.9
- Basic 1.1.1.1
- Banana 2.1.1.1
- Potato 3.1.1.1
## `Requirements`
@ -13,19 +13,17 @@
## `Use`
```powershell
.\vmrcli.exe [-h] [-v] [-i|-I] [-f] [-k] [-l] [-e] [-c] [-m] [-s] <api commands>
.\vmrcli.exe [-h] [-i|-I] [-k] [-D] [-v] [-c] [-m] [-s] <api commands>
```
Where:
- `h`: Print the help message.
- `v`: Print the version of vmrcli.
- `h`: Prints the help message.
- `i`: Enable interactive mode, use (-I) to disable the '>>' prompt.
- If set, any api commands passed on the command line will be ignored.
- `f`: Do not split input on spaces.
- `k`: The kind of Voicemeeter (basic, banana or potato). Use this to launch the GUI.
- `l`: Set log level, must be one of TRACE, DEBUG, INFO, WARN, ERROR, or FATAL
- `e`: Enable extra console output (toggle, set messages)
- `D`: Set log level 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=FATAL
- `v`: Enable extra console output (toggle, set messages)
- `c`: Load a user configuration (give the full file path)
- `m`: Launch the MacroButtons application
- `s`: Launch the StreamerView application
@ -41,23 +39,13 @@ Examples:
Launch basic GUI, set log level to INFO, Toggle Strip 0 Mute, print its new value, then decrease Bus 0 Gain by 3.8
```powershell
.\vmrcli.exe -kbasic -lINFO !strip[0].mute strip[0].mute bus[0].gain-=3.8
.\vmrcli.exe -kbasic -D2 !strip[0].mute strip[0].mute bus[0].gain-=3.8
```
Launch banana GUI, set log level to DEBUG, set Strip 0 label to podmic then print Strip 2 label
```powershell
.\vmrcli.exe -kbanana -lDEBUG strip[0].label=podmic strip[2].label
```
#### `String Commands With Spaces`
It may be desirable to send a string request containing spaces, for example to change an output device. By default the CLI splits such strings, to avoid this pass the `-f` flag. It's probably best to use this with single commands only due to its effect on how the CLI parses strings. Also note the inclusion of the double quotation marks, it seems the C API requires them.
```powershell
.\vmrcli.exe -lDEBUG -f bus[1].device.wdm='"Realtek Digital Output (Realtek(R) Audio)"'
.\vmrcli.exe -lDEBUG -f strip[0].label='"My Podmic"'
.\vmrcli.exe -kbanana -D1 strip[0].label=podmic strip[2].label
```
#### `Quick Commands`
@ -94,13 +82,13 @@ API commands follow the same rules as listed above. Entering `Q` or `q` will exi
Scripts can be loaded from text files, for example in Powershell:
```powershell
.\vmrcli.exe -lDEBUG $(Get-Content .\example_commands.txt)
.\vmrcli.exe -D1 $(Get-Content .\example_commands.txt)
```
You may also pipe a scripts contents to the CLI:
```powershell
$(Get-Content .\example_commands.txt) | .\vmrcli.exe -lDEBUG -I
$(Get-Content .\example_commands.txt) | .\vmrcli.exe -D1 -I
```
Multiple API commands can be in a single line, they may be separated by space, `;` or `,`.

View File

@ -1,71 +0,0 @@
version: '3'
dotenv: ['.env']
vars:
PROGRAM: vmrcli
SHELL: pwsh
CC: gcc
SRC_DIR: src
INC_DIR: include
OBJ_DIR: obj
BIN_DIR: bin
CPPFLAGS: -I{{.INC_DIR}} -MMD -MP {{if eq .LOG_USE_COLOR "yes"}}-DLOG_USE_COLOR{{end}}
CFLAGS: -O -Wall -W -pedantic -ansi -std=c2x
LDFLAGS: -Llib
LDLIBS: -lm
tasks:
default:
desc: Build vmrcli for Windows
deps: [build]
build:
desc: Build vmrcli for Windows
deps: [link]
link:
desc: Link all files in obj/ for Windows
deps: [compile]
cmds:
- |
{{.SHELL}} -Command "
if (!(Test-Path -Path '{{.BIN_DIR}}')) {
New-Item -ItemType Directory -Path '{{.BIN_DIR}}'
}
{{.CC}} {{.LDFLAGS}} {{.OBJ_DIR}}/*.o {{.LDLIBS}} -o {{.BIN_DIR}}/{{.PROGRAM}}.exe"
sources:
- '{{.OBJ_DIR}}/**'
generates:
- '{{.BIN_DIR}}/{{.PROGRAM}}.exe'
compile:
desc: Compile all files in src/ and include/ for Windows
cmds:
- |
{{.SHELL}} -Command "
if (!(Test-Path -Path '{{.OBJ_DIR}}')) {
New-Item -ItemType Directory -Path '{{.OBJ_DIR}}'
}
Get-ChildItem -Path '{{.SRC_DIR}}' -Filter '*.c' |
ForEach-Object { \$_.Name -replace '\.c$', '' } |
ForEach-Object { {{.CC}} {{.CPPFLAGS}} {{.CFLAGS}} -c {{.SRC_DIR}}/\$_.c -o {{.OBJ_DIR}}/\$_.o }"
sources:
- '{{.SRC_DIR}}/**'
- '{{.INC_DIR}}/**'
generates:
- '{{.OBJ_DIR}}/**'
clean:
desc: Remove all files in obj/ and bin/
cmds:
- |
{{.SHELL}} -Command "
if (Test-Path -Path '{{.OBJ_DIR}}') { Remove-Item -Path '{{.OBJ_DIR}}' -Recurse -Force }
if (Test-Path -Path '{{.BIN_DIR}}') { Remove-Item -Path '{{.BIN_DIR}}' -Recurse -Force }"

View File

@ -10,8 +10,6 @@
#include "VoicemeeterRemote.h"
#define IS_64_BIT sizeof(void *) == 8
PT_VMR create_interface();
#endif /* __IVMR_H__ */

View File

@ -15,7 +15,6 @@ struct quickcommand
};
void remove_last_part_of_path(char *fullpath);
int log_level_from_string(const char *level);
char *kind_as_string(char *s, int kind, int n);
char *version_as_string(char *s, long v, int n);
bool is_comment(char *s);

View File

@ -1,53 +1,38 @@
# Program name
program = vmrcli
# Compiler
CC = gcc
# Directories
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
# Executable and source/object files
EXE := $(BIN_DIR)/$(program).exe
SRC := $(wildcard $(SRC_DIR)/*.c)
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
# Conditional compilation flags for logging
LOG_USE_COLOR ?= yes
ifeq ($(LOG_USE_COLOR), yes)
CPPFLAGS := -Iinclude -MMD -MP -DLOG_USE_COLOR
else
CPPFLAGS := -Iinclude -MMD -MP
endif
# Compiler and linker flags
CFLAGS = -O -Wall -W -pedantic -ansi -std=c2x
LDFLAGS := -Llib
LDLIBS := -lm
# Phony targets
.PHONY: all clean
# Default target
all: $(EXE)
# Link the executable
$(EXE): $(OBJ) | $(BIN_DIR)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
# Compile source files to object files
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
# Create necessary directories
$(BIN_DIR) $(OBJ_DIR):
pwsh -Command New-Item -Path $@ -ItemType Directory
# Clean up generated files
clean:
pwsh -Command Remove-Item -Recurse $(BIN_DIR), $(OBJ_DIR) -force
pwsh -Command Remove-Item -Recurse $(EXE), $(OBJ_DIR) -force
# Include dependency files
-include $(OBJ:.o=.d)

View File

@ -1,9 +1,9 @@
/**
* @file interface.c
* @file ivmr.c
* @author Vincent Burel, Onyx and Iris (code@onyxandiris.online)
* @brief Functions for initializing the iVMR interface.
* Defines a single public function that returns a pointer to the interface.
* @version 0.11.0
* @version 0.10.0
* @date 2024-07-06
*
* @copyright Vincent Burel(c)2015-2021 All Rights Reserved
@ -14,7 +14,7 @@
*/
#include <windows.h>
#include "interface.h"
#include "ivmr.h"
#include "util.h"
#include "log.h"
@ -25,8 +25,10 @@
#define PRAGMA_Pop \
_Pragma("GCC diagnostic pop")
static T_VBVMR_INTERFACE iVMR;
static long initialize_dll_interfaces(PT_VMR vmr);
static bool registry_get_voicemeeter_folder(char *dll_fullpath);
static bool registry_get_voicemeeter_folder(char *szDir);
/**
* @brief Create an interface object
@ -36,14 +38,10 @@ static bool registry_get_voicemeeter_folder(char *dll_fullpath);
*/
PT_VMR create_interface()
{
PT_VMR vmr = malloc(sizeof(T_VBVMR_INTERFACE));
if (vmr == NULL)
{
log_error("malloc failed to allocate memory");
return NULL;
}
PT_VMR vmr = &iVMR;
int rep;
LONG rep = initialize_dll_interfaces(vmr);
rep = initialize_dll_interfaces(vmr);
if (rep < 0)
{
if (rep == -100)
@ -54,8 +52,7 @@ PT_VMR create_interface()
{
log_fatal("Error loading Voicemeeter dll with code %d", rep);
}
free(vmr);
vmr = NULL;
return NULL;
}
return vmr;
@ -64,30 +61,26 @@ PT_VMR create_interface()
/*******************************************************************************/
/** GET DLL INTERFACE **/
/*******************************************************************************/
#define DLL_FULLPATH_SZ 1024
#define DLL64_NAME "\\VoicemeeterRemote64.dll"
#define DLL32_NAME "\\VoicemeeterRemote.dll"
static long initialize_dll_interfaces(PT_VMR vmr)
{
HMODULE G_H_Module = NULL;
char dll_fullpath[DLL_FULLPATH_SZ];
char szDllName[1024];
memset(vmr, 0, sizeof(T_VBVMR_INTERFACE));
// get Voicemeeter installation directory
if (!registry_get_voicemeeter_folder(dll_fullpath))
if (!registry_get_voicemeeter_folder(szDllName))
{
// Voicemeeter not installed
return -100;
}
// use right dll according to O/S type
if (IS_64_BIT)
strncat(dll_fullpath, DLL64_NAME, DLL_FULLPATH_SZ - strlen(DLL64_NAME) - 1);
if (sizeof(void *) == 8)
strcat(szDllName, "\\VoicemeeterRemote64.dll");
else
strncat(dll_fullpath, DLL32_NAME, DLL_FULLPATH_SZ - strlen(DLL32_NAME) - 1);
strcat(szDllName, "\\VoicemeeterRemote.dll");
// Load Dll
G_H_Module = LoadLibrary(dll_fullpath);
G_H_Module = LoadLibrary(szDllName);
if (G_H_Module == NULL)
return -101;
@ -132,33 +125,33 @@ static long initialize_dll_interfaces(PT_VMR vmr)
if (vmr->VBVMR_Logout == NULL)
return -2;
if (vmr->VBVMR_RunVoicemeeter == NULL)
return -3;
return -2;
if (vmr->VBVMR_GetVoicemeeterType == NULL)
return -4;
return -3;
if (vmr->VBVMR_GetVoicemeeterVersion == NULL)
return -5;
return -4;
if (vmr->VBVMR_IsParametersDirty == NULL)
return -6;
return -5;
if (vmr->VBVMR_GetParameterFloat == NULL)
return -7;
return -6;
if (vmr->VBVMR_GetParameterStringA == NULL)
return -8;
return -7;
if (vmr->VBVMR_GetParameterStringW == NULL)
return -9;
return -8;
if (vmr->VBVMR_GetLevel == NULL)
return -10;
return -9;
if (vmr->VBVMR_SetParameterFloat == NULL)
return -11;
return -10;
if (vmr->VBVMR_SetParameters == NULL)
return -12;
return -11;
if (vmr->VBVMR_SetParametersW == NULL)
return -13;
return -12;
if (vmr->VBVMR_SetParameterStringA == NULL)
return -14;
return -13;
if (vmr->VBVMR_SetParameterStringW == NULL)
return -15;
return -14;
if (vmr->VBVMR_GetMidiMessage == NULL)
return -16;
return -15;
if (vmr->VBVMR_Output_GetDeviceNumber == NULL)
return -30;
@ -187,48 +180,50 @@ static long initialize_dll_interfaces(PT_VMR vmr)
/** GET VOICEMEETER DIRECTORY **/
/*******************************************************************************/
#define INSTALLER_DIR_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
#define INSTALLER_UNINST_KEY "VB:Voicemeeter {17359A74-1236-5467}"
#ifndef KEY_WOW64_32KEY
#define KEY_WOW64_32KEY 0x0200
#endif
#define UNINSTALL_KEY_SZ 256
#define UNINSTALL_PATH_SZ 1024
static bool registry_get_voicemeeter_folder(char *dll_fullpath)
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
char uninstall_key[UNINSTALL_KEY_SZ];
snprintf(uninstall_key, UNINSTALL_KEY_SZ, "%s\\%s", INSTALLER_DIR_KEY, INSTALLER_UNINST_KEY);
strcpy(szKey, uninstDirKey);
strcat(szKey, "\\");
strcat(szKey, INSTALLER_UNINST_KEY);
// open key
HKEY result;
LONG rep = RegOpenKeyEx(HKEY_LOCAL_MACHINE, uninstall_key, 0, KEY_READ, &result);
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, uninstall_key, 0, KEY_READ | KEY_WOW64_32KEY, &result);
rep = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ | KEY_WOW64_32KEY, &hkResult);
}
if (rep != ERROR_SUCCESS)
return false;
// read uninstall path from registry
DWORD pptype = REG_SZ;
DWORD len_uninstall_path = UNINSTALL_PATH_SZ;
char uninstall_path[UNINSTALL_PATH_SZ] = {0};
rep = RegQueryValueEx(result, "UninstallString", 0, &pptype, (unsigned char *)uninstall_path, &len_uninstall_path);
RegCloseKey(result);
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_last_part_of_path(uninstall_path);
snprintf(dll_fullpath, DLL_FULLPATH_SZ, uninstall_path);
remove_last_part_of_path(sss);
if (nnsize > 512)
nnsize = 512;
strncpy(szDir, sss, nnsize);
return true;
}

View File

@ -118,7 +118,7 @@ void log_set_quiet(bool enable)
int log_add_callback(log_LogFn fn, void *udata, int level)
{
for (int i = 0; i < MAX_CALLBACKS; ++i)
for (int i = 0; i < MAX_CALLBACKS; i++)
{
if (!L.callbacks[i].fn)
{
@ -163,7 +163,7 @@ void log_log(int level, const char *file, int line, const char *fmt, ...)
va_end(ev.ap);
}
for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; ++i)
for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++)
{
Callback *cb = &L.callbacks[i];
if (level >= cb->level)

View File

@ -2,7 +2,7 @@
* @file util.c
* @author Onyx and Iris (code@onyxandiris.online)
* @brief Utility functions.
* @version 0.11.0
* @version 0.10.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024
@ -12,7 +12,6 @@
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "log.h"
/**
* @brief Removes the last part of a path
@ -29,29 +28,6 @@ void remove_last_part_of_path(char *fullpath)
}
}
/**
* @brief Gets log level as int from string
* @param level Log level as string
* @return int Log level as int, or -1 if not found
*/
int log_level_from_string(const char *level)
{
if (strcmp(level, "TRACE") == 0)
return LOG_TRACE;
else if (strcmp(level, "DEBUG") == 0)
return LOG_DEBUG;
else if (strcmp(level, "INFO") == 0)
return LOG_INFO;
else if (strcmp(level, "WARN") == 0)
return LOG_WARN;
else if (strcmp(level, "ERROR") == 0)
return LOG_ERROR;
else if (strcmp(level, "FATAL") == 0)
return LOG_FATAL;
else
return -1;
}
/**
* @brief Converts Voicemeeter's kind into a string.
*
@ -116,7 +92,7 @@ bool is_comment(char *s)
*/
struct quickcommand *command_in_quickcommands(const char *command_key, const struct quickcommand *quickcommands, int n)
{
for (int i = 0; i < n; ++i)
for (int i = 0; i < n; i++)
{
if (strcmp(command_key, quickcommands[i].name) == 0)
{

View File

@ -2,7 +2,7 @@
* @file vmrcli.c
* @author Onyx and Iris (code@onyxandiris.online)
* @brief A Voicemeeter Remote Command Line Interface
* @version 0.11.0
* @version 0.10.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024
@ -13,29 +13,26 @@
#include <stdlib.h>
#include <getopt.h>
#include <windows.h>
#include "interface.h"
#include "ivmr.h"
#include "wrapper.h"
#include "log.h"
#include "util.h"
#define USAGE "Usage: .\\vmrcli.exe [-h] [-v] [-i|-I] [-f] [-k] [-l] [-e] [-c] [-m] [-s] <api commands>\n" \
#define USAGE "Usage: .\\vmrcli.exe [-h] [-i|-I] [-k] [-D] [-v] [-c] [-m] [-s] <api commands>\n" \
"Where: \n" \
"\th: Print the help message\n" \
"\tv: Print the version number\n" \
"\th: Prints the help message\n" \
"\ti: Enable interactive mode, use (-I) to disable the '>>' prompt\n" \
"\tf: Do not split input on spaces\n" \
"\tk: The kind of Voicemeeter (basic, banana, potato)\n" \
"\tl: Set log level, must be one of TRACE, DEBUG, INFO, WARN, ERROR, or FATAL\n" \
"\te: Enable extra console output (toggle, set messages)\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" \
"\tc: Load a user configuration (give the full file path)\n" \
"\tm: Launch the MacroButtons application\n" \
"\ts: Launch the StreamerView application"
#define OPTSTR ":hvk:msc:iIfl:e"
#define OPTSTR ":hk:msc:iID:v"
#define MAX_LINE 4096 /* Size of the input buffer */
#define RES_SZ 512 /* Size of the buffer passed to VBVMR_GetParameterStringW */
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
#define DELIMITERS " \t;,"
#define VERSION "0.12.0"
/**
* @enum The kind of values a get call may return.
@ -61,13 +58,12 @@ struct result
} val;
};
static bool eflag = false;
static bool vflag = false;
static void terminate(PT_VMR vmr, char *msg);
static void usage();
static enum kind set_kind(char *kval);
static void interactive(PT_VMR vmr, bool with_prompt, char *delimiters);
static void parse_input(PT_VMR vmr, char *input, char *delimiters);
static void interactive(PT_VMR vmr, bool with_prompt);
static void parse_input(PT_VMR vmr, char *input);
static void parse_command(PT_VMR vmr, char *command);
static void get(PT_VMR vmr, char *command, struct result *res);
@ -77,10 +73,9 @@ int main(int argc, char *argv[])
mflag = false,
sflag = false,
cflag = false,
fflag = false,
with_prompt = true;
int opt;
int log_level = LOG_WARN;
int dvalue;
char *cvalue;
enum kind kind = BANANAX64;
@ -89,16 +84,13 @@ int main(int argc, char *argv[])
usage();
}
log_set_level(log_level);
log_set_level(LOG_WARN);
opterr = 0;
while ((opt = getopt(argc, argv, OPTSTR)) != -1)
{
switch (opt)
{
case 'v':
printf("vmrcli version %s\n", VERSION);
exit(EXIT_SUCCESS);
case 'k':
kind = set_kind(optarg);
if (kind == UNKNOWN)
@ -123,24 +115,21 @@ int main(int argc, char *argv[])
case 'i':
iflag = true;
break;
case 'f':
fflag = true;
break;
case 'l':
log_level = log_level_from_string(optarg);
if (log_level != -1)
case 'D':
dvalue = atoi(optarg);
if (dvalue >= LOG_TRACE && dvalue <= LOG_FATAL)
{
log_set_level(log_level);
log_set_level(dvalue);
}
else
{
log_warn(
"-l arg out of range, expected TRACE, DEBUG, INFO, WARN, ERROR, or FATAL\n"
"-D arg out of range, expected value from 0 up to 5\n"
"Log level will default to LOG_WARN (3).\n");
}
break;
case 'e':
eflag = true;
case 'v':
vflag = true;
break;
case '?':
log_fatal("unknown option -- '%c'\n"
@ -169,9 +158,10 @@ int main(int argc, char *argv[])
if (rep != 0)
{
if (rep == -2)
terminate(vmr, "Timeout logging into the API.");
log_fatal("Timeout logging into the API.");
else
terminate(vmr, "Error logging into the Voicemeeter API");
log_fatal("Eror logging into the Voicemeeter API");
exit(EXIT_FAILURE);
}
if (mflag)
@ -194,47 +184,30 @@ int main(int argc, char *argv[])
clear(vmr, is_pdirty);
}
char *delimiter_ptr = DELIMITERS;
if (fflag)
{
delimiter_ptr++; /* skip space delimiter */
}
if (iflag)
{
puts("Interactive mode enabled. Enter 'Q' to exit.");
interactive(vmr, with_prompt, delimiter_ptr);
interactive(vmr, with_prompt);
}
else
{
for (int i = optind; i < argc; ++i)
for (int i = optind; i < argc; i++)
{
parse_input(vmr, argv[i], delimiter_ptr);
parse_input(vmr, argv[i]);
}
}
rep = logout(vmr);
if (rep != 0)
{
terminate(vmr, "Error logging out of the Voicemeeter API");
log_fatal("Error logging out of the Voicemeeter API");
return EXIT_FAILURE;
}
else
{
log_info("Successfully logged out of the Voicemeeter API");
return EXIT_SUCCESS;
}
log_info("Successfully logged out of the Voicemeeter API");
free(vmr);
return EXIT_SUCCESS;
}
/**
* @brief Write fatal error log, free dyn allocated memory then exit
*
* @param vmr Pointer to the iVMR interface
* @param msg Fatal error message
*/
static void terminate(PT_VMR vmr, char *msg)
{
log_fatal(msg);
free(vmr);
exit(EXIT_FAILURE);
}
/**
@ -256,11 +229,11 @@ static void usage()
static enum kind set_kind(char *kval)
{
if (strcmp(kval, "basic") == 0)
return IS_64_BIT ? BASICX64 : BASIC;
return sizeof(void *) == 8 ? BASICX64 : BASIC;
else if (strcmp(kval, "banana") == 0)
return IS_64_BIT ? BANANAX64 : BANANA;
return sizeof(void *) == 8 ? BANANAX64 : BANANA;
else if (strcmp(kval, "potato") == 0)
return IS_64_BIT ? POTATOX64 : POTATO;
return sizeof(void *) == 8 ? POTATOX64 : POTATO;
else
return UNKNOWN;
}
@ -272,9 +245,8 @@ static enum kind set_kind(char *kval)
*
* @param vmr Pointer to the iVMR interface
* @param with_prompt If true, prints the interactive prompt '>>'
* @param delimiters A string of delimiter characters to split each input line
*/
static void interactive(PT_VMR vmr, bool with_prompt, char *delimiters)
static void interactive(PT_VMR vmr, bool with_prompt)
{
char input[MAX_LINE];
size_t len;
@ -283,11 +255,12 @@ static void interactive(PT_VMR vmr, bool with_prompt, char *delimiters)
printf(">> ");
while (fgets(input, MAX_LINE, stdin) != NULL)
{
input[(len = strcspn(input, "\n"))] = 0;
if (len == 1 && toupper(input[0]) == 'Q')
input[strcspn(input, "\n")] = 0;
if ((len = strlen(input)) == 1 && toupper(input[0]) == 'Q')
break;
parse_input(vmr, input, delimiters);
parse_input(vmr, input);
memset(input, 0, len); /* reset input buffer */
if (with_prompt)
printf(">> ");
@ -301,20 +274,19 @@ static void interactive(PT_VMR vmr, bool with_prompt, char *delimiters)
*
* @param vmr Pointer to the iVMR interface
* @param input Each input line, from stdin or CLI args
* @param delimiters A string of delimiter characters to split each input line
*/
static void parse_input(PT_VMR vmr, char *input, char *delimiters)
static void parse_input(PT_VMR vmr, char *input)
{
if (is_comment(input))
return;
char *token, *p;
token = strtok_r(input, delimiters, &p);
token = strtok_r(input, DELIMITERS, &p);
while (token != NULL)
{
parse_command(vmr, token);
token = strtok_r(NULL, delimiters, &p);
token = strtok_r(NULL, DELIMITERS, &p);
}
}
@ -341,7 +313,7 @@ static void parse_command(PT_VMR vmr, char *command)
if (qc_ptr != NULL)
{
set_parameters(vmr, qc_ptr->fullcommand);
if (eflag)
if (vflag)
{
printf("Setting %s\n", qc_ptr->fullcommand);
}
@ -359,7 +331,7 @@ static void parse_command(PT_VMR vmr, char *command)
if (res.val.f == 1 || res.val.f == 0)
{
set_parameter_float(vmr, command, 1 - res.val.f);
if (eflag)
if (vflag)
{
printf("Toggling %s\n", command);
}
@ -373,7 +345,7 @@ static void parse_command(PT_VMR vmr, char *command)
if (strchr(command, '=') != NULL) /* set */
{
set_parameters(vmr, command);
if (eflag)
if (vflag)
{
printf("Setting %s\n", command);
}

View File

@ -2,7 +2,7 @@
* @file wrapper.c
* @author Onyx and Iris (code@onyxandiris.online)
* @brief Provides public functions that wrap the iVMR calls
* @version 0.11.0
* @version 0.10.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024