9 Commits

Author SHA1 Message Date
8d9e70b79a patch bump 2024-07-09 13:14:52 +01:00
d7d42e4b21 upd makefile to compile for c2x
replace fallthrough comment with fallthrough attribute
2024-07-09 12:59:46 +01:00
babec7abbb revert func signatures, we're getting compile warnings anyway 2024-07-09 12:58:06 +01:00
b2bdd21da5 add USAGE, OPTSTR macros
rename help() to usage()

log_warn() an unknown option

condense set_kind()
2024-07-09 12:43:32 +01:00
88fe1f5782 reword 2024-07-08 18:02:35 +01:00
82823687db minor bump 2024-07-08 18:01:10 +01:00
3d00c7dd4f upd parse_input() desc 2024-07-08 17:31:24 +01:00
c95ff0e163 add :, delimiters to parse_input()
remove replace_blanks_with_single_space()
2024-07-08 17:29:23 +01:00
48bb15e8f2 upd util.h 2024-07-08 16:39:03 +01:00
8 changed files with 81 additions and 132 deletions

View File

@@ -78,7 +78,7 @@ You may also pipe a scripts contents to the CLI:
$(Get-Content .\example_commands.txt) | .\vmrcli.exe -D1 -i
```
Multiple API commands can be in a single line but they should be space separated.
Multiple API commands can be in a single line, they may be separated by space, `;` or `,`.
## `Build`

View File

@@ -687,43 +687,43 @@ extern "C"
/* 'C' STRUCTURED INTERFACE */
/******************************************************************************/
typedef long long(__stdcall *T_VBVMR_Login)(void);
typedef long long(__stdcall *T_VBVMR_Logout)(void);
typedef long long(__stdcall *T_VBVMR_RunVoicemeeter)(long vType);
typedef long(__stdcall *T_VBVMR_Login)(void);
typedef long(__stdcall *T_VBVMR_Logout)(void);
typedef long(__stdcall *T_VBVMR_RunVoicemeeter)(long vType);
typedef long long(__stdcall *T_VBVMR_GetVoicemeeterType)(long *pType);
typedef long long(__stdcall *T_VBVMR_GetVoicemeeterVersion)(long *pVersion);
typedef long(__stdcall *T_VBVMR_GetVoicemeeterType)(long *pType);
typedef long(__stdcall *T_VBVMR_GetVoicemeeterVersion)(long *pVersion);
typedef long long(__stdcall *T_VBVMR_IsParametersDirty)(void);
typedef long long(__stdcall *T_VBVMR_GetParameterFloat)(char *szParamName, float *pValue);
typedef long long(__stdcall *T_VBVMR_GetParameterStringA)(char *szParamName, char *szString);
typedef long long(__stdcall *T_VBVMR_GetParameterStringW)(char *szParamName, unsigned short *wszString);
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 long(__stdcall *T_VBVMR_GetLevel)(long nType, long nuChannel, float *pValue);
typedef long long(__stdcall *T_VBVMR_GetMidiMessage)(unsigned char *pMIDIBuffer, long nbByteMax);
typedef long long(__stdcall *T_VBVMR_SendMidiMessage)(unsigned char *pMIDIBuffer, long nbByteMax);
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 long(__stdcall *T_VBVMR_SetParameterFloat)(char *szParamName, float Value);
typedef long long(__stdcall *T_VBVMR_SetParameters)(char *szParamScript);
typedef long long(__stdcall *T_VBVMR_SetParametersW)(unsigned short *szParamScript);
typedef long long(__stdcall *T_VBVMR_SetParameterStringA)(char *szParamName, char *szString);
typedef long long(__stdcall *T_VBVMR_SetParameterStringW)(char *szParamName, unsigned short *wszString);
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 long(__stdcall *T_VBVMR_Output_GetDeviceNumber)(void);
typedef long long(__stdcall *T_VBVMR_Output_GetDeviceDescA)(long zindex, long *nType, char *szDeviceName, char *szHardwareId);
typedef long long(__stdcall *T_VBVMR_Output_GetDeviceDescW)(long zindex, long *nType, unsigned short *wszDeviceName, unsigned short *wszHardwareId);
typedef long long(__stdcall *T_VBVMR_Input_GetDeviceNumber)(void);
typedef long long(__stdcall *T_VBVMR_Input_GetDeviceDescA)(long zindex, long *nType, char *szDeviceName, char *szHardwareId);
typedef long long(__stdcall *T_VBVMR_Input_GetDeviceDescW)(long zindex, long *nType, unsigned short *wszDeviceName, unsigned short *wszHardwareId);
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 long(__stdcall *T_VBVMR_AudioCallbackRegister)(long mode, T_VBVMR_VBAUDIOCALLBACK pCallback, void *lpUser, char szClientName[64]);
typedef long long(__stdcall *T_VBVMR_AudioCallbackStart)(void);
typedef long long(__stdcall *T_VBVMR_AudioCallbackStop)(void);
typedef long long(__stdcall *T_VBVMR_AudioCallbackUnregister)(void);
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 long(__stdcall *T_VBVMR_MacroButton_IsDirty)(void);
typedef long long(__stdcall *T_VBVMR_MacroButton_GetStatus)(long nuLogicalButton, float *pValue, long bitmode);
typedef long long(__stdcall *T_VBVMR_MacroButton_SetStatus)(long nuLogicalButton, float fValue, long bitmode);
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
{

View File

@@ -8,9 +8,8 @@
#ifndef __UTIL_H__
#define __UTIL_H__
void remove_last_part_of_path(char *szPath);
int replace_blanks_with_single_space(char *s, size_t len);
void remove_last_part_of_path(char *fullpath);
char *kind_as_string(char *s, int kind, int n);
char *version_as_string(char *, long v, int n);
char *version_as_string(char *s, long v, int n);
#endif /* __UTIL_H__ */

View File

@@ -15,7 +15,7 @@ ifeq ($(LOG_USE_COLOR), yes)
else
CPPFLAGS := -Iinclude -MMD -MP
endif
CFLAGS = -O -Wall -W -pedantic -ansi -std=c99
CFLAGS = -O -Wall -W -pedantic -ansi -std=c2x
LDFLAGS := -Llib
LDLIBS := -lm

View File

@@ -3,7 +3,7 @@
* @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.5.0
* @version 0.7.0
* @date 2024-07-06
*
* @copyright Vincent Burel(c)2015-2021 All Rights Reserved

View File

@@ -2,7 +2,7 @@
* @file util.c
* @author Onyx and Iris (code@onyxandiris.online)
* @brief Utility functions.
* @version 0.5.0
* @version 0.7.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024
@@ -31,47 +31,6 @@ void remove_last_part_of_path(char *fullpath)
}
}
/**
* @brief Replaces multiple spaces and tabs with single spaces
*
* @param s The string to be reduced
* @param len Current length of the string
* @return int New length of the string
*/
int replace_blanks_with_single_space(char *s, size_t len)
{
int j = 0;
int count = 0;
if (len == 1 && isblank(s[0]))
{
s[0] = '\0';
return len;
}
if (len < 2)
return len;
for (int i = 0; s[i] != '\0'; i++)
{
if (isblank(s[i]))
{
count++;
}
else
{
if (count >= 1)
{
count = 0;
s[j++] = ' ';
}
s[j++] = s[i];
}
}
s[j] = '\0';
return j;
}
/**
* @brief Converts Voicemeeter's kind into a string.
*

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.5.0
* @version 0.7.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024
@@ -21,6 +21,17 @@
#include "log.h"
#include "util.h"
#define USAGE "Usage: .\\vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-m] [-s] <api commands>\n" \
"Where: \n" \
"\th: Prints the help message\n" \
"\ti: Enable interactive mode\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" \
"\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 ":hk:msc:iD:v"
#define MAX_LINE 512
/**
@@ -47,10 +58,10 @@ struct result
static bool vflag = false;
void help(void);
static void usage(void);
enum kind set_kind(char *kval);
void interactive(PT_VMR vmr);
void parse_input(PT_VMR vmr, char *input, int len);
void parse_input(PT_VMR vmr, char *input);
void parse_command(PT_VMR vmr, char *command);
void get(PT_VMR vmr, char *command, struct result *res);
@@ -67,19 +78,16 @@ int main(int argc, char *argv[])
if (argc == 1)
{
help();
exit(EXIT_SUCCESS);
usage();
}
log_set_level(LOG_WARN);
while ((opt = getopt(argc, argv, "hk:msc:iD:v")) != -1)
opterr = 0;
while ((opt = getopt(argc, argv, OPTSTR)) != -1)
{
switch (opt)
{
case 'h':
help();
exit(EXIT_SUCCESS);
case 'k':
kind = set_kind(optarg);
if (kind == UNKNOWN)
@@ -117,8 +125,20 @@ int main(int argc, char *argv[])
case 'v':
vflag = true;
break;
case '?':
log_warn("unknown option -- '%c'\n"
"Try .\\vmrcli.exe -h for more information.",
optopt);
exit(EXIT_FAILURE);
case ':':
log_warn("missing argument for option -- '%c'\n"
"Try .\\vmrcli.exe -h for more information.",
optopt);
exit(EXIT_FAILURE);
case 'h':
[[fallthrough]];
default:
abort();
usage();
}
}
@@ -160,7 +180,7 @@ int main(int argc, char *argv[])
{
for (int i = optind; i < argc; i++)
{
parse_input(vmr, argv[i], strlen(argv[i]));
parse_input(vmr, argv[i]);
}
}
@@ -179,19 +199,10 @@ int main(int argc, char *argv[])
/**
* @brief prints the help message
*/
void help()
static void usage()
{
puts(
"Usage: .\\vmrcli.exe [-h] [-i] [-k] [-D] [-v] [-c] [-m] [-s] <api commands>\n"
"Where: \n"
"\th: Prints the help message\n"
"\ti: Enable interactive mode\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"
"\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");
puts(USAGE);
exit(EXIT_SUCCESS);
}
/**
@@ -204,30 +215,13 @@ void help()
enum kind set_kind(char *kval)
{
if (strcmp(kval, "basic") == 0)
{
if (sizeof(void *) == 8)
return BASICX64;
else
return BASIC;
}
return sizeof(void *) == 8 ? BASICX64 : BASIC;
else if (strcmp(kval, "banana") == 0)
{
if (sizeof(void *) == 8)
return BANANAX64;
else
return BANANA;
}
return sizeof(void *) == 8 ? BANANAX64 : BANANA;
else if (strcmp(kval, "potato") == 0)
{
if (sizeof(void *) == 8)
return POTATOX64;
else
return POTATO;
}
return sizeof(void *) == 8 ? POTATOX64 : POTATO;
else
{
return UNKNOWN;
}
}
/**
@@ -240,16 +234,15 @@ enum kind set_kind(char *kval)
void interactive(PT_VMR vmr)
{
char input[MAX_LINE];
size_t len;
printf(">> ");
while (fgets(input, MAX_LINE, stdin) != NULL)
{
input[strcspn(input, "\n")] = 0;
if ((len = strlen(input)) == 1 && toupper(input[0]) == 'Q')
if (strlen(input) == 1 && toupper(input[0]) == 'Q')
break;
parse_input(vmr, input, len);
parse_input(vmr, input);
memset(input, 0, MAX_LINE); /* reset input buffer */
printf(">> ");
@@ -257,23 +250,21 @@ void interactive(PT_VMR vmr)
}
/**
* @brief Walks through each line split by a space delimiter.
* @brief Walks through each line split by " \t;," delimiters.
* Each token is passed to parse_command()
*
* @param vmr Pointer to the iVMR interface
* @param input Each input line, from stdin or CLI args
* @param len The length of the input line
*/
void parse_input(PT_VMR vmr, char *input, int len)
void parse_input(PT_VMR vmr, char *input)
{
char *token;
char *token, *p;
replace_blanks_with_single_space(input, len);
token = strtok(input, " ");
token = strtok_r(input, " \t;,", &p);
while (token != NULL)
{
parse_command(vmr, token);
token = strtok(NULL, " ");
token = strtok_r(NULL, " \t;,", &p);
}
}

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.5.0
* @version 0.7.0
* @date 2024-07-06
*
* @copyright Copyright (c) 2024